A learning resource for developers.
Put the planet in your hand with the real day/night line computed from the clock, city lights on the dark side, the International Space Station propagated from its orbital elements with its trail, and your own patch of the planet marked.
ns-perspective-earth-small.mov
- Earth — where the station is right now, how fast it's going, whether it's in sunlight, how many people are on it; and your spot: sunrise/sunset, golden hour. Tap anywhere on the planet to learn what time it is there and who's awake.
- Look up — the next time the station will be visible over your sky (dark ground, sunlit spacecraft), with rise/peak/set directions, a live "where is it right now" pointer, and the next passes.
- Perspective — words from people who have seen the planet from outside, a few scale facts, and a counter of humans born since you opened the app.
Just orbital mechanics, a directional light, a clock, and eight billion people.
- ISS elements from CelesTrak (cached for 6 h; a bundled TLE keeps the globe
truthful offline). Propagation via
satellite.js@5(SGP4). Cross-checked with wheretheiss.at to ~0.05°. - Sun position: USNO approximate solar coordinates (subsolar point, observer elevation, sunrise/sunset).
- Crew: open-notify.org, with a bundled fallback.
- Textures: three.js planet textures (MIT); stars: Solar System Scope (CC BY 4.0).
Everything native is called directly from TypeScript (no plugins).
| Capability | iOS | Android |
|---|---|---|
| The globe | SceneKit scene built in TS: textured sphere, cloud layer, atmosphere shell, Metal shader modifiers for the terminator + city lights + rim light, HDR bloom | android.graphics.Canvas custom View: 5,900-dot land matrix, ellipse-based terminator shading, glow gradients, batched drawPoints, Choreographer frame loop |
| Location & place names | CLLocationManager + CLGeocoder (incl. the place's IANA time zone) |
LocationManager + Geocoder |
| Time formatting | NSDateFormatter (the iOS V8 runtime has no Intl) |
SimpleDateFormat |
| Haptics | UIImpactFeedbackGenerator & friends |
VibrationEffect |
| Panel glass | UIVisualEffectView with Liquid Glass (UIGlassEffect) on iOS 26, material blur before |
translucent drawable |
| Mode switcher | native UISegmentedControl via SegmentedBar |
custom bar with a sliding pill (the platform SegmentedBar is a dated TabHost) |
| Frame loop | CADisplayLink |
Choreographer |
The panel wraps its content, caps at half the screen (then scrolls), and glides between heights when you switch modes; it dims while you're handling the planet.
One camera model (globe-view.common.ts) drives both renderers: yaw/pitch/zoom
with inertia, fly-to choreography, gestures and hit-testing are shared; only the
drawing differs.
The UI is Angular 22 (zoneless, signals). An OverviewStore holds the clock, sun,
station state, your location and passes; effects push changes into the globe.
Bundled with Vite via @nativescript/vite (vite.config.mts, bundler: 'vite' in nativescript.config.ts).
npm install # runs patch-package for @analogjs/vite-plugin-angular
ns run ios # iOS 26 simulator: Liquid Glass; earlier iOS: material blur
ns run androidSet a simulator location to see the beacon and passes:
xcrun simctl location <udid> set 45.5152,-122.6784 / adb emu geo fix -122.6784 45.5152.
src/app/
globe/ GlobeView (common camera model, iOS SceneKit + Android Canvas renderers, shaders, land dots)
space/ sun.ts (solar geometry), iss.ts (SGP4, passes, sunlit test), geo.ts, people.ts
native/ location, geocode, clock (native formatters), haptics, glass-view
state/ OverviewStore — signals + commands
home/ page: globe, top chrome, place card, panel host
panel/ PanelComponent — Earth / Look up / Perspective
perspective/ reflections