A screenshot of the Sky Tracker app

Sky Tracker

View project

sveltesuncalc

Sky Tracker is a web app that displays sky info like sunrise, sunsets, and moon phases. It was designed and built for mobile, but works just fine on desktop.

This is another project that I will personally use. When shooting photography, I often want to know what the sun (or moon) is doing on a particular day. This app easily shows sunrise, sunset, day length, and moon phases. It also allows the user to “time travel”, showing how the day length or moon phases will change over time.

Technically, it’s built with Svelte and composed of many derived stores. Here’s the time store, for example:

// using svelte's writable store
import { writable } from "svelte/store"

interface Time {
    date: Date;
    hours: number;
    minutes: number;
    paused: boolean;
}

// wrapper function to start, stop, and update time store
const timeInit = () => {

    let d = new Date();
    const initial: Time = {
        date: d,
        hours: d.getHours(),
        minutes: d.getMinutes(),
        paused: false,
    };
    const { subscribe, set, update } = writable(initial);
    let interval: number | undefined;

    return {
        subscribe,
        start: () => {
            const updateClock = () => {
                let newDate = new Date();
                set({
                    date: newDate,
                    hours: newDate.getHours(),
                    minutes: newDate.getMinutes(),
                    paused: false,
                });
            }
            updateClock();
            interval = setInterval(updateClock, 1000);
        },
        updateTime: (updatedDate: Date) => {
            // omitted for brevity
        },
        pause: () => {
            // omitted for brevity
        },
    };
};

export const time = timeInit();

Once we have the time store ticking, more useful stores can be derived:

// derive minutes since unix epoch, used for most time-related things
export const epochMinutes = derived(
    time,
    ($time) => dateToEpoch($time.date)
);

// derive date string
export const date = derived(
    time,
    ($time) => dateString($time.date),
    dateString(new Date())
);

Most of the app relies on epoch minutes to reduce state updates. This allows the app to update once per minute rather than once per second.

There were some challenges during development:

  • Tons and tons of date math while working with Date objects
  • Figuring out how to draw and animate moon phases
  • Keeping the design clean and the scope small
  • Drawing the arcs in a performant, reuseable way

Another feature to mention, this is a progressive web app. This means it can be installed and be taken completely offline. All date, sky, and moon calculations don’t need the internet, thanks to the amazing suncalc npm package. Pretty cool.

Feel free to check it out and use it. I know I will!