← Portfolio

Technical Documentation

Astronomical Calendar

A cross-platform React Native app for exploring astronomical events, photography light windows, and halachic Zmanim by date and location

React Native · TypeScript · Zustand · Luxon · Astronomy Engine · Hebcal  ·  iOS & Android


Origin

The web calendar works. But a calendar you open in a browser is different from one you tap into instantly, wherever you are, whenever you look up at the sky. The app exists because those are two different experiences. The web version is something you sit down with. The native app is something you reach for in a moment of curiosity — standing outside at night, wondering what phase the moon is in, wanting to know right now. That immediacy changes the whole feel of it.


Overview

This cross-platform mobile app adapts the calculation engine and interaction model from bachtogauss.com/calendar into a native iOS and Android experience. It is designed as a practical celestial calendar: select a day, change location, review sun and moon data, inspect moon phases and eclipses on the calendar grid, and toggle the supporting systems that matter to you.

The most interesting engineering work is in separating astronomical calculations, halachic calculations, moon phase data, eclipse data, and UI state into clear independent modules — then running them in parallel while preserving partial results if one source fails. The web calendar was the reference implementation; this project is the native re-architecture.

The app coordinates multiple independent calculation domains (astronomical rise/set events, photography light windows, moon phases, eclipse detection, and halachic Zmanim), location input paths, timezone formatting, user settings, custom iconography, and native mobile concerns behind one interface. Each isolated domain is run in parallel with fault-tolerant merging so that a failure in one domain does not degrade the others.


Features

Calendar

Sun and moon dashboard

Photography windows

Upcoming events

Halachic Zmanim

Location

Settings


Architecture

The app is organized around calculation services, UI components, and a small global state store. Calculation domains are kept strictly independent — astronomical and halachic data are fetched in parallel and merged only after each path completes.

src/
  components/          Reusable UI: calendar grid, legend, location input, cards
  components/icons/    Bottom tab icons
  components/symbols/  Moon phase and eclipse SVG symbols
  lib/                 Library access wrappers
  navigation/          React Navigation configuration
  screens/             Calendar, Legend, and Settings screens
  services/            Location, geocoding, moon data, and merged time services
  store/               Zustand calendar and settings store
  styles/              Shared theme, colors, typography, spacing
  types/               Shared TypeScript interfaces
  utils/               Astronomy, halachic, eclipse, moon phase, and time helpers

Calculation pipeline

The pipeline is designed so that each domain operates independently and the UI degrades gracefully when any value is unavailable — returning null for that value rather than blocking the whole view.

Key files

CalendarScreen.tsx Main composition layer: calendar, pager, moon data loading, time loading
CalendarGrid.tsx Fixed-height month grid, date navigation, phase and eclipse markers
timeService.ts Parallel orchestration of astronomy and halachic calculations with fault-tolerant fallbacks
moonDataService.ts Unified moon phase, eclipse, illumination, and age pipeline
astronomyUtils.ts Sunrise, sunset, moonrise, moonset, blue hour, golden hour, illumination, moon direction
halachicUtils.ts Hebcal-backed Zmanim with per-value error isolation
eclipseUtils.ts Solar and lunar eclipse searches and symbol mapping
geocodingService.ts Location parsing, search ranking, geocoding, reverse geocoding, coordinate formatting
LocationField.tsx Debounced manual search, GPS flow, dropdown selection, location status display
calendarStore.ts Centralized date, location, display preference, and feature-toggle state via Zustand

Tech Stack

Mobile framework React Native 0.81
Language TypeScript
UI foundation React Native Paper, custom styles, custom fonts
Navigation React Navigation bottom tabs
State management Zustand
Date/time handling Luxon
Astronomy calculations astronomy-engine
Halachic calculations @hebcal/core
Location @react-native-community/geolocation
Geocoding OpenStreetMap Nominatim
Testing Jest, React Test Renderer, standalone calculation scripts

Engineering Decisions

Fault-tolerant data merging

Astronomy and halachic data are fetched separately and merged only after each path completes. A failure in one domain does not erase the other domain's usable results. Individual Zmanim values are each wrapped in per-value error isolation — a single bad calculation does not blank the entire Zmanim card.

Unified moon data source

Moon phases, current moon age, current illumination, and eclipse markers are all calculated through moonDataService in a single pass. This ensures the calendar grid and detail cards always agree on the selected month and date — no possibility of the grid showing a different phase than the dashboard.

Platform-aware layout

The calendar grid uses explicit percentage widths and a fixed six-row structure to avoid platform-specific flexbox inconsistencies and month-to-month height changes. Northern and southern hemisphere orientation is handled explicitly for first and last quarter moon symbols, which appear mirrored depending on hemisphere.

Small global store

Zustand stores only app-level state shared across screens: selected date, visible month, location, loading and error state, hemisphere, time format, feature toggles, and Zmanim system. Component-local state stays local.

Native-friendly migration from web

A web_reference/ directory preserves source material from the original browser implementation. The React Native code keeps the calculation intent while replacing DOM-oriented patterns with native navigation, gesture paging, React Native Paper controls, and platform font registration.


Testing and Verification

The repository includes both React Native test coverage and calculation-focused Node scripts that can be run independently of the full app build:


Known Limitations


Roadmap


Attribution