DEV Community

Cover image for Skywatch: An Offline-First Gemma Stargazing PWA Where Screen Time is the Enemy
Swetabh Tripathy
Swetabh Tripathy

Posted on

Skywatch: An Offline-First Gemma Stargazing PWA Where Screen Time is the Enemy

Hacktoberfest Open-Source AI Challenge Week 1: Touch Grass Submission 🌿

Skywatch: An Offline-First, Voice-First Stargazing PWA That Keeps the Screen the Shortest Part of Your Night

This is an official submission for the Hacktoberfest Open-Source AI Challenge: Week 1 & 2 ("Touch Grass"), targeting the **Overall Winner* and Best Use of Gemma categories.*


🌌 The Problem: Stargazing Apps Keep Your Face Buried in Blue Light

Most stargazing apps are interactive planetarium simulators. They expect you to hold a brightly glowing screen up to the sky, pinch-to-zoom across thousands of catalog items, and continuously interact with the display.

There's just one problem: it takes 20 to 30 minutes for human eyes to produce rhodopsin and adapt to dark skies. Every time you look down at a mobile UI, you reset your dark adaptation. You went outside to look at the universe, but ended up staring at glass.

We built Skywatch to invert this paradigm: open-weight AI that gets people outside and makes the screen the shortest part of the entire experience.

Plan your night βž” Find best dark spot βž” Get spoken cues βž” Capture & ask βž” Get a Night Card showing how little screen time you used.
Enter fullscreen mode Exit fullscreen mode

🌿 Why Open Innovation Matters Here

When building for the outdoors, closed-source cloud APIs fundamentally fail:

  1. Zero Backcountry Signal: The best stargazing locations (Bortle 1–3 state parks, mountain ridges, nature reserves) have zero cellular connectivity. A cloud LLM API like OpenAI or Claude produces a loading spinner in the dark.
  2. Location Privacy: Stargazers frequently observe in isolated, remote clearings at night. Transmitting real-time GPS coordinates to commercial cloud servers is an unnecessary privacy exposure.
  3. Local Tool Orchestration with Gemma: By running Gemma 3 locally via Ollama (http://localhost:11434), inference happens completely on-device. Gemma acts as a strict tool-calling orchestrator without fabricating astronomy facts.
  4. Single-Config Model Swapping: Stargazers on low-power devices can swap to gemma:2b or step up to gemma3:4b with a single command (npm run swap-model -- <model>), without modifying application code.

πŸ—οΈ Architecture: Gemma as a Grounded Tool-Calling Planner

Gemma must never invent astronomical phenomena. It orchestrates deterministic offline tools that compute ground truth:

flowchart TD
    subgraph UI ["Client PWA (Offline-First, Vite + React + Tailwind)"]
        PV[1. Plan View]
        SV[2. Dark Sky Scout]
        WV[3. Watch Session - Red-Light Mode]
        CV[4. Capture & Ask]
        NC[5. Night Card - Screen Seconds]
    end

    subgraph Planner ["Open-Weight Local AI Loop"]
        LLM["Gemma 3 (via local Ollama)"]
        DET[Deterministic Astronomy Fallback]
        ZOD[Zod Schema Validation]
    end

    subgraph Tools ["Offline Computation Tools"]
        T_SKY["get_sky_events()"]
        T_WTH["get_weather()"]
        T_SCOUT["score_locations()"]
        T_CTX["get_user_context()"]
    end

    subgraph Engines ["Offline Astronomy & Physics Engines"]
        ASTRO["astronomy-engine (Ephemeris, Moon Phase, Alt/Az)"]
        SAT["satellite.js SGP4 Propagator (ISS Passes)"]
        METEOR["Meteor Catalog (Perseids, Geminids, Orionids)"]
        SCOUT_ENG["Dark Sky Scout (Bortle Grid + Moon Wash + Clouds)"]
    end

    PV --> LLM
    LLM --> T_SKY & T_WTH & T_SCOUT & T_CTX
    T_SKY --> ASTRO & SAT & METEOR
    T_SCOUT --> SCOUT_ENG
    LLM -.->|Offline / Timeout| DET
    DET --> ZOD
    LLM --> ZOD
    ZOD --> PV
    PV --> WV
    WV --> NC

The Tool-Calling Agent Loop

When a user asks for a 30-minute stargazing session:

  1. Model proposes tool calls:
   { "type": "tool_call", "tool": "get_sky_events", "arguments": { "lat": 40.71, "lon": -74.0 } }
Enter fullscreen mode Exit fullscreen mode
  1. App executes offline mathematics:
    • astronomy-engine calculates real-time altitudes, azimuths, and magnitudes for Venus, Jupiter, Saturn, Mars, and the Moon.
    • satellite.js propagates the ISS orbit via SGP4 from a cached NORAD Two-Line Element (TLE) set.
    • Evaluates active annual meteor shower radiants (Quadrantids, Lyrids, Perseids, Geminids, Orionids).
  2. Model synthesizes the timed plan:
    • Generates a timed hit list staggered across the user's available window.
    • Computes a calculated "Leave By" time giving observers a 15-minute window to transit and settle night vision.
    • Validates all output against a strict Zod schema (SkyPlanSchema).
    • If Ollama is offline or returns invalid JSON, the app instantly and seamlessly falls back to the deterministic astronomy engine without failing.

🎯 The 7 Core Features Built for "Touch Grass"

1. PLAN: Configurable Agent Modes

Controlled by a modular modes.json config:

  • Beginner Stargazer: High-contrast naked-eye landmarks and bright planets with simple cardinal cues.
  • Family & Kids: Engaging storytelling hooks, Moon crater spotting, and ISS satellite flybys.
  • Quick Look (20 min): Laser-focused 20-minute hit list prioritizing the highest-altitude bright targets.
  • Poor Weather / Urban: Filters for high-magnitude objects (Moon, Jupiter, Venus) that punch through light smog or partial cloud breaks.

2. SCOUT: Dark Sky Scout

Combines an offline light-pollution atlas grid calibrated to the New World Atlas of Artificial Night Sky Brightness (Falchi et al., 2016), cached cloud cover, and topocentric Moon sky-wash into a physics-backed 0–100 score with a crisp one-line reason (e.g. "Pristine Bortle 2 dark sky with crystal atmospheric clarity; Milky Way structure visible").

3. WATCH: Ultra-Dark Red-Light Mode

Designed for one-hand use in the dark:

  • True black background (#050202) with soft OLED crimson accents (#ef4444, #fca5a5) to preserve rhodopsin dark adaptation.
  • One Big Tap Target: Start session with a single thumb tap.
  • Stays Completely Quiet: Speaks through TTS only when a target is approaching ("ISS visible in two minutes. Look northwest.").
  • DeviceOrientation Compass: Uses the device magnetometer to provide relative directional cues ("Look slightly to your right, about halfway up. Jupiter is visible.").
  • Voice Commands: Supports "What's that?", "What's next?", "How long?", and "Tell me about this", backed by large one-tap dark voice cards for windy nights.

4. CAPTURE & ASK: Grounded Ephemeris Q&A

Users can snap an outdoor photo and ask questions ("Did I capture a meteor streak or a satellite?"). Skywatch grounds answers strictly against the computed sky math for that exact second and coordinate.

Scientific Honesty: The local Gemma model runs in text-only mode and does not perform optical feature detection. The app honestly discloses this to the user and evaluates physical plausibility (e.g. matching against active ISS passes or meteor shower radiant geometry) rather than hallucinating false confirmation.

5. KEEP: Night Cards & The Headline Stat

At the end of a session, Skywatch generates an official Night Card.

SCREEN-SECONDS is the headline stat.

Instead of rewarding endless app engagement, Skywatch measures real foreground screen time using the browser's visibilitychange API and active display timers. An observer can spend 45 minutes outside under the stars with only 42 screen-seconds logged!

6. COMMUNITY: One-Tap Circles (No Feeds, No Chat)

Minimal nearby stargazing circles where users can RSVP with one tap. Backed by a clean mock dataset (communitySessions.json) with zero algorithmic distraction, zero followers, and zero chat.

7. STREAKS: Touching Grass Consistently

Consecutive-night outdoor streaks and cumulative hours under dark skies calculated purely from stored Night Cards in IndexedDB.


✈️ The Proofs: Verification & Integrity

1. Airplane-Mode Proof (Zero Outbound Leaks)

We built an automated offline verification script (npm run verify-offline) and unit test suite that locks the network and tests the entire pipeline:

========================================================================
✈️  SKYWATCH AIRPLANE-MODE OFFLINE VERIFICATION PROOF
Validating zero-network execution across Plan, Scout, Watch & Night Card
========================================================================

Testing Step 1: PLAN (Offline Astronomy Generation)...
Testing Step 2: SCOUT (Offline Dark Sky Grid Ranking)...
Testing Step 3: WATCH (Compass Orientation & Screen Tracking)...
Testing Step 4: KEEP / NIGHT CARD & STREAKS...

πŸ“‹ OFFLINE VERIFICATION SUMMARY CHECKLIST
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ (index) β”‚ Pipeline                β”‚ Status    β”‚ Details                                                β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ 0       β”‚ '1. PLAN'               β”‚ 'βœ… PASS' β”‚ Generated 2 celestial targets without network.         β”‚
β”‚ 1       β”‚ '2. SCOUT'              β”‚ 'βœ… PASS' β”‚ Ranked dark sky spots with Bortle & Moon math.         β”‚
β”‚ 2       β”‚ '3. WATCH'              β”‚ 'βœ… PASS' β”‚ Compass relative heading & screen-seconds verified.    β”‚
β”‚ 3       β”‚ '4. KEEP & STREAKS'     β”‚ 'βœ… PASS' β”‚ Saved Night Card. Headline stat: 42s screen-time.       β”‚
β”‚ 4       β”‚ '5. NETWORK LEAK CHECK' β”‚ 'βœ… PASS' β”‚ 0 outbound network calls were made across the pipeline.β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
πŸŽ‰ 100% OFFLINE PROOF COMPLETE: Zero network activity.
Enter fullscreen mode Exit fullscreen mode

2. Model-Swap & Benchmark Proof

Switch models with a single CLI command:

npm run swap-model -- gemma:2b
npm run swap-model -- gemma3:4b
Enter fullscreen mode Exit fullscreen mode

And run side-by-side prompt benchmarks:

npm run compare-models -- gemma3:4b gemma:2b
Enter fullscreen mode Exit fullscreen mode

Outputs side-by-side latency, target counts, Zod schema validation passes, and plan quality across tactical, beginner, and family prompts.


πŸ”— Links & Code


πŸ› οΈ Try It Yourself

# 1. Clone & install
git clone https://github.com/Tswetabh/sky-watch.git
cd sky-watch
npm install

# 2. Pull local Gemma model
ollama pull gemma3:4b

# 3. Run test suite & airplane verification
npm test
npm run verify-offline

# 4. Start local PWA
npm run dev
Enter fullscreen mode Exit fullscreen mode

Open http://localhost:5173 on your mobile browser, tap "Add to Home Screen", put your phone in your pocket, and go look up at the stars. πŸŒŒπŸ”­

Top comments (0)

Some comments may only be visible to logged-in visitors. Sign in to view all comments.