Commit graph

20 commits

Author SHA1 Message Date
SkateSpots
13ebea685e fix(auth): keep signup alive across page cards; sanitize trip links 2026-10-28 00:05:28 +07:00
SkateSpots
828684cf15 feat(i18n): add Hindi (24 dictionaries, 25 codes, all 100%)
- Full 8,703-key Hindi dictionary in src/i18n/hi (7 namespace batches),
  placeholders verified, only 2% identical strings (brand/protocol names).
- Register hi in Language/LANGUAGE_LOADERS, detectLanguage (hi-IN),
  LanguageToggle (🇮🇳, हिन्दी) and dateFnsI18n (hi-IN).
- Lazy-load Noto Sans Devanagari for hi via lib/localeFonts.ts (renamed from
  cjkFonts.ts) and add it to the CSS font stack; other locales don't download it.
- check-i18n covers hi: 24 dictionaries / 25 codes at 100%; tsc/tests/build green.
2026-10-26 16:35:53 +07:00
SkateSpots
7e48884eb9 feat(map,i18n): single-copy world clamp + regional flags + pt-PT
- Map: min zoom = smallest integer zoom whose 256*2^z world covers the
  viewport (no grey bands, no duplicated continents). Horizontal wrap is
  restored (worldCopyJump, no longitude maxBounds) so Hawaii/Pacific are
  reachable by dragging; vertical panning stays clamped.
- Flags: real SVGs for Catalonia, Basque Country, Galicia and England
  (no Unicode region flags exist; English is not the UK). Portuguese now has
  Brasil (pt) and Portugal (pt-PT).
- pt-PT shares the pt dictionary with a European drift for the visible chrome
  (Guardar, Palavra-passe, Autocarro, Utilizador, ...).
- check-i18n covers pt-PT: 24 codes at 100%; tsc/tests/build green.
2026-10-26 16:09:21 +07:00
SkateSpots
d4c6261b81 feat(i18n): add Catalan, Basque and Galician (23 locales, all 100%)
- Full dictionaries (8,703 keys each) in src/i18n/{ca,eu,gl}, 7 namespace
  batches, composed with deepMerge; placeholders verified, 2-4% identical
  strings are only brand/protocol names.
- Register in Language/LANGUAGE_LOADERS, detectLanguage (before es),
  LanguageToggle (CA/EU/GL text badges - no Unicode region flags exist) and
  dateFnsI18n (ca-ES/eu-ES/gl-ES).
- check-i18n.mjs now covers ca/eu/gl: all 23 locales at 100%, tsc/tests/build
  green.
2026-10-26 15:56:56 +07:00
SkateSpots
cc250b4d0b perf(fonts): lazy-load CJK fonts per locale (~16MB font payload off the boot path)
Kanit (th), Noto Sans JP (ja) and Noto Sans KR (ko) were imported statically in main.tsx, so every visitor downloaded ~16MB of CJK font files. They're now loaded on demand once per locale (lib/cjkFonts.ts, wired in LanguageContext), so non-CJK users never fetch them and CJK users get their font after the first paint.
2026-10-12 19:52:54 +07:00
SkateSpots
6407310213 feat(relay): cut over community relay to self-hosted Newlay
Point SKATE_RELAY, the default relay pools, the DM/CVM/zap relay arrays, the cvm-server + push-service defaults, and the archive default at wss://relay.skate-spots.org, keeping the legacy hosted relay as a fallback during the client-update window. Restored 115/115 archived events; the relay runs behind Caddy with TLS. Docs + AGENTS.md updated.
2026-10-12 12:38:13 +07:00
SkateSpots
feac9f764b i18n: register 10 locales (framework + scaffold); ro/el partial 2026-10-08 14:59:27 +07:00
SkateSpots
1dd23c1549 i18n(ko): separate South and North Korean options, one flag each 2026-10-08 12:45:09 +07:00
SkateSpots
1460b06277 i18n: lazy-load locales + register 8 new (pt fr de it nl pl ru ko) with fonts 2026-10-07 21:23:39 +07:00
SkateSpots
ab05973ff0 i18n(ja): add Japanese as fourth locale (plumbing + font + batch 1 shell) 2026-10-07 17:21:18 +07:00
SkateSpots
b8c306125c i18n(th): batch 2 — map (mapUi + mapPage) + AGENTS note 2026-10-06 13:35:20 +07:00
SkateSpots
9357386bbd i18n(es): batch 3 part 2 — locale-aware dates & relative times
- New src/lib/dateFnsI18n.ts re-exports date-fns with formatDistanceToNow /
  formatDistanceToNowStrict / formatDistance / format defaulting to the active
  locale, plus dateLocaleCode() for native toLocale{Date,Time}String calls.
- LanguageProvider keeps the locale in sync during render, so the first paint is
  already in-language.
- Codemod: 11 date-fns imports now use the shim; ~39 native date/time calls pass
  the app locale code instead of undefined/[]/hardcoded 'en-US'. Number
  .toLocaleString() calls are deliberately untouched.
2026-10-02 15:19:38 +07:00
SkateSpots
09735375c2 feat(i18n): Spanish (Castellano) — infra + Map/Spots, Marketplace, Lab (batch 1)
- First-visit language auto-detect (Spanish devices land in es; stored choice wins).
- Sasquatch AI replies in the app language (skate trick names kept English).
- i18n safety net: scripts/check-i18n.mjs wired into npm test — fails on any t()
  key missing from en/es or any en/es key drift.
- ~1,680 new keys (2,297 total) across mapUi / spotUi / marketUi / labUi and
  ~65 files wired to t(): Map, spots (detail/create/edit/chat), marketplace,
  trades, offers, escrow, shipping, The Lab, /become/* forms, coaches, skaters.
- Policy: only skate TRICK names stay English; user-generated content untouched.
2026-10-01 23:57:20 +07:00
SkateSpots
b2a6108eeb refactor: split non-component exports (react-refresh) into their own modules
Removes the last react-refresh disables by splitting exports instead:
- contexts/language.ts: Language/Translations types + LanguageContext +
  useTranslation/useT (LanguageProvider stays a component-only file); 12
  importers repointed.
- lib/sortOptions.ts: calculatePopularity + calculateDistance (out of SortDropdown)
- lib/trustFilter.ts: TrustFilterLevel + filterByTrustLevel (out of TrustFilter)
- EventCountdown: deleted the unused useEventStatus hook
- NewsletterPage: dropped the NEWSLETTER_ISSUES re-export shim
- AGENTS.md updated (lint stays clean with no blanket disables)

Gate: 101 tests, 0 errors/warnings, boot smoke green.
2026-09-26 23:29:42 +07:00
SkateSpots
c0aec3d912 chore(lint): reach zero warnings (react-refresh)
The last 7 react-refresh warnings are dev-only HMR DX from intentional
component+hook/helper colocations (EventCountdown, SortDropdown, TrustFilter,
LanguageContext, NewsletterPage). Splitting them into new files is broad import
churn for no runtime benefit, so each carries a justified file-level disable.

npm test: 0 errors, 0 warnings, 101 tests; boot smoke green.
2026-09-26 22:23:45 +07:00
SkateSpots
30ef511e78 feat(relays): NIP-17 DM inbox relays (kind 10050)
- RelayMetadata.dmRelays; Relays UI to add/remove, publishing kind 10050
- NostrSync fetches the user's 10050 on login (alongside 10002)
- DMs deliver gift wraps to recipients' + own DM relays (fallback: write relays)
  and read from own DM relays + NIP-65 read relays
- useDmRelays() to look up others' DM relay lists

Also fixes a latent data-loss bug: NostrSync's 10002 fetch replaced
relayMetadata wholesale, which would wipe the new local/blocked/dm lists on
login — it now merges. 'Trusted' category intentionally skipped (no distinct
behaviour -> no empty UI); documented in AGENTS.md.
2026-09-26 21:32:53 +07:00
SkateSpots
e75c4a8355 feat(relays): Local + Blocked relay categories
Add a purposeful subset of Amethyst-style relay categories (not a full clone):
- App-local 'Local relays' (never published; added to reads+writes)
- App-local 'Blocked relays' (excluded from every read/write)
- src/lib/relays.ts: resolveRelays()/useRelays() + URL normalisation
- NostrProvider req/event routers go through resolveRelays (blocklist applied)
- RelayListManager: Local/Blocked editors; NIP-65 save now preserves the new
  lists instead of overwriting relayMetadata

Deliberately omitted (documented in AGENTS.md): KeyPackage (10051, no MLS
consumer) and proxy/broadcast/private-home (no such discovery model here).
Follow-up noted: a few hooks still read config.relayMetadata.relays directly.
2026-09-26 21:26:13 +07:00
shakespeare.diy
bd9b71095d Citrine: optional local on-device relay for instant reads + offline backup (1.3.0)
Integrates Citrine (github.com/greenart7c3/Citrine), an Android app that runs a
full Nostr relay locally on the phone. Because it's "just a relay URL", it folds
into the existing useSkateRelays / nostr.relay() machinery with no new protocol.

What it buys SkateSpots:
- Instant reads: a localhost hit (~1ms) is queried first, remote relays run in
  parallel and reconcile — every skate-content surface feels faster.
- Offline-in-the-field: reads work with no signal; writes land on-device and
  publish to remote when connectivity returns.
- Resilience/backup: a durable local copy of the user's own events survives
  public-relay outages and addressable-event eviction.
- Privacy: local-first data can lean on the device instead of public relays.

Design / safety:
- Android-only (Capacitor native + platform === 'android'); renders nothing and
  never probes localhost on iOS/desktop web. Mixed-content ws:// is already
  permitted via capacitor allowMixedContent.
- Opt-in only via config.useCitrineRelay (default off). No data is ever routed
  through Citrine unless the user enables it AND a relay is actually reachable.
- Reachability probe (short-lived WebSocket) cached through react-query, shared
  app-wide, re-checked periodically + on focus, with a manual Recheck button.
- When active, the local URL is prepended to reads and included in writes; the
  read-relay set feeds getQueryKeySuffix so caches refetch automatically when
  Citrine comes/goes.
- Encryption unchanged: Stash/DMs stay NIP-44 encrypted regardless of
  destination — the Settings card states this explicitly. Local ≠ plaintext.

New: src/lib/citrine.ts, src/hooks/useCitrine.ts, CitrineCard in the Relays
settings screen. AppConfig gains useCitrineRelay (zod-validated, optional).

On-device verification still needed: confirm Android permits ws://127.0.0.1
cleartext to localhost (network security config) once Citrine is running.

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-09-08 18:53:16 +07:00
shakespeare.diy
e29d35f1e4 fix: restore full skate-spots source tree from misplaced src/src/ copy
The entire skate-spots codebase was accidentally copied into src/src/ and
public/public/ instead of src/ and public/ directly. This left the real
src/ directory as blank MKStack template stubs, explaining why the landing
page showed the default template instead of SkateSpots.

Changes made:
- Copied all files from src/src/ up to src/ (App.tsx, AppRouter.tsx, main.tsx,
  all pages, components, hooks, contexts, lib, i18n, test)
- Copied all files from public/public/ up to public/ (images, manifest, etc.)
- Deleted src/src/ and public/public/ nested directories
- Removed HelloWorld.tsx template stub from pages/
- Retained the previously fixed index.css (Tailwind v3 directives)

Full skate-spots feature set is now active:
- All 30+ routes (map, events, spots, coaches, marketplace, wallet, etc.)
- NWCProvider, LanguageProvider, PWAInstallPrompt, AmberCallbackHandler
- Skate community relays (goskatespots.nostr1.com, wotr.relatr.xyz, etc.)
- Outfit Variable font, Amber pre-check in main.tsx
- All hooks (useSkateSpots, useCoaches, useZaps, etc.)
- i18n support (en/es)

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-06-15 22:18:28 +07:00
shakespeare.diy
06fae294b8 New project created with Shakespeare
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-06-15 19:49:07 +07:00