Live: values.nathantowianski.com
A spinnable 3D globe of what the world actually wants — without forcing anyone onto a left–right line.
Instead of opposing sliders, the platform asks one honest question: "What do you want for where you live?" — and lets you pick every hope you hold, even ones the usual framing says you must choose between (a thriving environment and a booming economy; personal freedom and strong community). When you pick a pair like that, the map celebrates it and shows how many of your neighbours agree — because most "either/or" debates are false choices.
You can recolor the globe by different data sources:
- Community — what people here say they want (one map per hope: "share who want a thriving environment", etc.).
- World Happiness — life evaluations and their drivers.
- Cultural values — Hofstede's six dimensions of national culture.
- Human Development — UNDP's Human Development Index.
…and you can travel to other worlds. Tap the faint Moon or Mars drifting in the background and the globe becomes that world — pick named regions (Tranquility Base, Olympus Mons, Jezero Crater…) and say what those places should stand for.
Flip on Satellite imagery (sidebar) to drape the real planet texture under the value overlay — borders and colors stay perfectly aligned because the texture is projected with the same map projection that draws the countries.
Inspired by Hoodmaps and the look of a 3D satellite globe, with cool, optimistic space vibes — and cheap to run.
- The globe is a 2D
<canvas>drawn withd3-geo's orthographic projection — no WebGL, no satellite tiles. ~124 KB of JS total. - Only anonymous tallies are stored for community responses (how many people want each thing, plus a few "both/and" co-endorsement counts) — O(1) updates, one round-trip reads a whole world.
- Reference data is pre-joined at build time into one ~18 KB JSON; no third-party calls at runtime.
- Zero-config deploy. Everything works out of the box; community responses upgrade from "your own local vote" to "shared & persistent" when you add a database.
npm install
npm run dev # http://localhost:3000Push to GitHub → import at vercel.com/new. Standard Next.js app — nothing to configure.
By default community responses live only in your own browser. To save & share them across everyone, connect Supabase (free tier) — two steps:
- SQL Editor → New query → paste
supabase/schema.sqland Run. (Creates onevalue_aggregatestable.) - Project Settings → API → copy the
service_rolekey and set it asSUPABASE_SERVICE_ROLE_KEYin Vercel (Project → Settings → Environment Variables → add → Redeploy). It's a secret — server-only, neverNEXT_PUBLIC_*.
The sidebar footer then shows "Live & shared · Supabase," or visit
/api/health to confirm from a URL — it returns { storage, backend, connected }
(e.g. {"backend":"supabase","connected":true}).
The project URL is already wired into lib/store.ts (it's public, not secret),
so the service-role key is all you need; set SUPABASE_URL to point at a
different project. The key is used only server-side and bypasses row-level
security, so with RLS on the table stays private. Each world is stored separately
and only anonymous tallies are written — never individual answers.
Prefer Redis? Upstash / Vercel KV also work — set UPSTASH_REDIS_REST_URL +
UPSTASH_REDIS_REST_TOKEN (or KV_*) instead.
Link previews (iMessage, WhatsApp, Twitter, Slack…) use a generated share card,
star favicon and apple-touch-icon. They resolve to absolute URLs automatically on
Vercel; for a custom domain, set NEXT_PUBLIC_SITE_URL=https://yourdomain.
Regenerate the card and icons with npm run build:images.
public/reference-data.json is generated and committed by
scripts/build-data.mjs, which pulls from open,
widely-cited sources and joins them to the globe's country ids:
| Layer | Source |
|---|---|
| World Happiness | World Happiness Report 2024 |
| Cultural values | Hofstede dimension data |
| Human Development | UNDP HDI 2022 |
| Country crosswalk | datasets/country-codes |
Refresh anytime with npm run build:data. The reference layers are convenience
snapshots for visualization — for authoritative figures, consult the sources
above.
- The "wants" (and the "you can want both" tension pairs) live in
lib/values.ts. Add or rephrase a hope and the form, maps, legend and panel all follow. - Worlds (Earth/Moon/Mars, their colors and named regions) live in
lib/worlds.ts. Add a moon of Jupiter if you like. - Data sources & color scales live in
lib/sources.ts.
app/
page.tsx renders the client app
api/aggregate/route.ts GET ?world=… community tallies (one read)
api/submit/route.ts POST a response (worldId + regionId + wants)
components/
App.tsx state, world switching, sidebar, search, panels
Globe.tsx canvas globe: drag/zoom/tap, starfield, background worlds
ValueForm.tsx the "what do you want?" cards
lib/
values.ts worlds.ts sources.ts colors.ts aggregate.ts store.ts types.ts
scripts/
build-data.mjs fetches + joins the reference datasets
build-images.mjs renders the OG share card + icons
build-bodies.mjs renders planet images + satellite textures
supabase/
schema.sql one-table schema for shared responses
public/
countries-110m.json Natural Earth countries (world-atlas)
reference-data.json generated reference data (committed)
body-*.png shaded planet images for the travel bodies
tex-*.jpg equirectangular maps for satellite mode
Country geometry is from world-atlas (Natural Earth, public domain). Lunar/Martian regions are hand-placed at approximate real coordinates. Planet textures (travel bodies + satellite mode) are Solar System Scope maps (CC BY 4.0, based on NASA imagery), projected to spheres at build time and served in a fast low-res tier plus a 2k tier the client upgrades to progressively.
Contributions and ideas are welcome — see CONTRIBUTING.md.
Most content lives in one place each: wants in lib/values.ts, data sources in
lib/sources.ts, translations in lib/i18n.ts, worlds in lib/worlds.ts.
MIT © Nathan Towianski. Data and texture sources retain their own licenses (linked above).

