Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

161 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Bitcoin Spaces

Repository/internal working name: Freedom Tech City.

An isolated fork of Bitcoin Spaces Globe that combines a reviewed third-space layer with a static global snapshot of current BTC Map merchants.

V1 status

Public site: https://btcspaces.freedomlab.nyc/

  • 18 curated third spaces grouped by country
  • 28,876 current BTC Map merchant markers
  • 11 reviewed merchant duplicates suppressed in favor of curated third-space records
  • No BTC Map communities
  • Neutral country polygons; no political/regime color layer
  • Circular local third-space logos with orange rays
  • Reviewed website links, the official X mark, and a purple-ostrich Nostr mark on third-space cards
  • Small BTC Map-blue (#0099af) merchant markers
  • Exact-location selection and closer globe targeting

Curated third spaces remain first-class records even when the same venue appears on BTC Map. The reviewed exclusions live in config/btcmap-third-space-exclusions.json.

Data sources

The tracked merchant snapshot is generated deterministically at web/public/data/btcmap-places.json. It is a one-time V1 snapshot, not a live API proxy.

Build

From the repository root:

python3 scripts/init_db.py
python3 scripts/seed_nodes.py
python3 scripts/export_globe.py --output web/public/data
python3 scripts/build_global_btcmap.py --timeout 120
cd web
npm ci
npm test
npm run build

The global importer:

  • makes one field-limited request for id,lat,lon,updated_at;
  • validates response status, final URL, content type, size, IDs, timestamps, and coordinates;
  • applies the reviewed third-space exclusion mapping;
  • sorts records deterministically;
  • atomically replaces the prior snapshot only after complete validation.

Architecture

  • Browser: React, Vite, react-globe.gl, and a GPU-instanced Three.js merchant layer
  • Curated store: SQLite STRICT tables generated from the reviewed manifest
  • Static delivery: data/globe.json, hash-addressed nearby-merchant shards, and compact data/btcmap-places.json
  • Identity: local logo assets and a reviewed social manifest; no runtime X, Brainstorm, Nostr-relay, or BTC Map image queries
  • Safety: the inherited source remote is read-only for pushes in this local clone

Verification

python3 -m unittest discover -s tests -p 'test_*.py' -v
cd web
npm test
npm run build

The suites cover migrations, manifest validation, deterministic exports, BTC Map response hardening, reviewed deduplication, local logo and social-identity coverage, merchant instance rendering, country grouping, neutral country treatment, accessibility behavior, responsive UI contracts, release retention, and startup payload budgets. npm run build fails if the light application entry, total JavaScript, initial branding, or globe snapshot exceeds its checked budget.

Generate a fresh, review-only social candidate report with:

python3 scripts/research_space_socials.py \
  --output /tmp/freedom-tech-city-social-candidates.json

The command never changes the reviewed production manifest. Follow docs/SOCIAL_IDENTITY_WORKFLOW.md to verify candidates before publication.

For the real-browser gate, run one fixed-port production preview and keep it alive for the complete local QA loop:

# Terminal 1
cd web && npm run preview -- --host 127.0.0.1 --port 4173 --strictPort

# Terminal 2, from the repository root
python3 scripts/qa_ui.py --evidence-dir /tmp/freedom-tech-city-qa

During iteration, select only the affected surface; repeat --check to combine checks:

python3 scripts/qa_ui.py --check mobile --evidence-dir /tmp/freedom-tech-city-mobile-qa
python3 scripts/qa_ui.py --check desktop --evidence-dir /tmp/freedom-tech-city-desktop-qa
python3 scripts/qa_ui.py --check gallery --check media --evidence-dir /tmp/freedom-tech-city-card-qa

Run the command without --check for the final local and live gates. The complete gate runs bounded desktop, gallery, media, 390×844 mobile, and reduced-motion lanes. Separating gallery and media sweeps keeps the desktop smoke gate fast and makes failures attributable. The checks cover logo hover hit-area/tooltip timing, country-tooltip suppression, console/page errors, in-viewport geometry, selection, focus restoration, and screenshots. The mobile check captures both the default collapsed directory/globe view and the expanded internally scrolling directory.

UI tuning

Globe logo diameter is controlled by one CSS custom property in web/src/styles.css:

--globe-logo-size: 45px;
--globe-logo-hover-target-size: 69px;

Both values are CSS pixels. The visible logo remains 45px across, while the transparent hover target is 69px across—12px of extra trigger space on every side. Changing the hover-target value adjusts only interaction tolerance. The custom name label begins appearing immediately with a 60ms fade, and the country label is suppressed while a third-space logo is hovered or focused. Changing the logo-size value updates every normal globe logo; hover and selected logos retain the same proportional scale automatically. Country groups are ordered by space count descending. Count ties use the westernmost third-space longitude, and spaces within each country use the same west-to-east order. The sweep begins at -125° longitude, just offshore of the contiguous United States west coast, and wraps around the globe.

The globe surface uses the exact earth-night.jpg color texture and earth-topology.png bump texture from the official react-globe.gl world-population example, vendored under web/public/textures/ for reliable local serving. Only the globe surface, relief, and default light-blue atmosphere are reused; the example's star field, population bars, data, and other elements are intentionally excluded. Transparent country polygons preserve the existing country hover labels and neutral borders without obscuring the reference land/sea texture.

The top-right search matches third spaces locally and submits explicit geography searches to OpenStreetMap Nominatim for countries, states, cities, and other geographic places. BTC Map merchants are never included in the search index or passed to the search component. Geography requests occur only when the user submits the form; the UI does not send autocomplete requests.

Merchant-node colors are controlled by the ordered trial list in web/src/ui-colors.js. Append a trial to make it active everywhere—the GPU layer, data-model visuals, and legend marker—while preserving every earlier color for rollback and comparison.

Trial Color Tried
BTC Map blue #0099af 2026-07-15
Bitcoin orange (active) #f7931a 2026-07-15

Teable review mirror

SQLite remains canonical for third-space IDs, names, and map status. scripts/sync_spaces_to_teable.py idempotently mirrors all rows into the Teable Third Spaces Review view, preserves the human-managed Reviewed? value, and verifies that no canonical records are missing. Full data deployments run this sync before the build; code-only deployments deliberately skip it. The local Hermes scheduler also runs it every six hours.

The review view exposes only Third Space, On Map?, and Reviewed?. The stable SQLite ID synchronization key is hidden. Reviewed? is a single-select field with Yes, No, and Partially.

Run a manual sync with:

python3 scripts/sync_spaces_to_teable.py

Future synchronization

No recurring BTC Map source refresh is enabled. The incremental BTC Map design—including updated_since, deletion reconciliation, cursor safety, full-reconciliation fallback, and reviewed exclusion maintenance—is documented in docs/plans/FUTURE_BTCMAP_SYNC.md.

Deployment

The public site is served from the atomically promoted web/current release through the persistent ai.bitcoinspaces.globe LaunchAgent and the existing Freedom Lab Cloudflare Tunnel route.

Use the full publisher after canonical data changes:

./deploy/refresh_and_build.sh

Use the network-independent path for frontend, CSS, server, or documentation-adjacent release changes that do not modify exported data:

./deploy/refresh_and_build.sh --code-only

Both paths validate the built globe snapshot, promote a content-addressed release atomically, retain the previous release for rollback, and prune only older validated release directories. The static server keeps HTML and public data fresh, gives hashed Vite assets a one-year immutable cache, and gives unversioned media a short revalidating cache so repeat visits do not needlessly hit the Raspberry Pi origin.

About

Interactive globe of Bitcoin third spaces and public data layers

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages