Flight Timer
Documentation · v0.1.2
Flight Timer is an offline-first progressive web app for pilots who want a precise, structured record of what happened and when during a flight. Think of it as a lap timer meets a flight logbook: you tap a button the moment something happens — engine start, takeoff, a maneuver, landing — and the app timestamps it to the second.
At the end of the flight you have a complete, timestamped log of events that can be exported as JSON or in the Open Aviation Data Standard (OADS) format for archival or import into other tools.
Design Constraints
Flight Timer is built for use in the cockpit, not just on a desk. Every interface decision reflects the realities of flying: gloves, turbulence, direct sunlight on the display, and one hand on the controls.
- Large tap targets: Minimum 60–70 px button height. The primary event buttons are large enough to tap reliably with a gloved hand.
- No swipe gestures for critical actions: Deleting a session or ending a flight requires an explicit tap confirmation — not a swipe that can be triggered accidentally.
- One-handed use: The event log screen is designed so the most common actions are reachable with a thumb.
- Sunlight legibility: High-contrast cream background with dark text. No low-contrast gray-on-gray UI.
- Screen-on during flight: Wake lock is requested when a session is active so the screen does not sleep mid-flight.
First Launch
On first launch the app displays the template picker. Select a template that matches your typical flight type — you can always change it before starting any individual session.
The app will prompt you to allow location access if GPS is enabled in Settings. Granting access lets the app resolve your nearest airport at takeoff and landing. You can deny the prompt and use the app without GPS; airport names will simply not appear in session records.
Built-In Templates
Templates define the list of named events shown during a session. Each event appears as a large button on the logging screen; tapping it records a timestamp. Built-in templates cover the most common general aviation flight profiles:
| Template | Phases | Sample Events |
|---|---|---|
| Standard Flight | Pre-flight, In-flight, Post-flight | Preflight Start, Engine Start, Taxi Out, Takeoff, Top of Climb, Cruise, Descent, Landing, Engine Shutdown, Tie-down |
| Training / Lesson | Pre-flight, Lesson, Post-flight | Briefing Start, Engine Start, Takeoff, Maneuver Area, Pattern Entry, Touch & Go, Full Stop, Debriefing Start |
| Pattern Work | Pre-flight, Pattern, Post-flight | Engine Start, Runway Lineup, Takeoff, Crosswind, Downwind, Base, Final, Touch & Go |
| Cross-Country | Departure, En Route, Arrival | Engine Start, Takeoff, Top of Climb, Each Waypoint, Descent, Landing, Engine Shutdown |
Built-in templates cannot be edited or deleted. To modify a built-in template, duplicate it into a custom template first (tap the copy icon next to the template name in the template picker).
Custom Templates
Custom templates are stored in localStorage under the key
flight-timer-templates. They survive browser restarts and app updates
but are specific to your device and browser. Use the JSON export to back them up
or move them to another device.
You can create as many custom templates as you like. Common use cases include:
- Aircraft-specific checklists (e.g., a tailwheel aircraft with distinct three-point vs. wheel landing events)
- Specific maneuver sequences for a checkride or proficiency flight
- Instrument approaches with specific gate events (FAF, MAP, missed approach)
Template Editor
Open the Template Editor from the Settings screen or from the template picker by tapping + New Template. The editor lets you:
- Name the template
- Add, rename, reorder, and delete events
- Assign each event to a phase label (optional) — phases appear as section headers on the logging screen
Events are displayed on the logging screen in the order they appear in the template. Drag handles let you reorder events. Changes are saved automatically as you edit.
Starting a Session
From the home screen, select a template and tap START FLIGHT. The app immediately begins the session timer and requests a wake lock so the screen stays on.
Each session has a unique ID generated at start time. The session is written to IndexedDB immediately — if the app is closed mid-flight, the partial session is preserved and can be reviewed or completed from the History screen.
Tapping Events
The logging screen displays your template events as large, full-width buttons. Tap an event button to record it. Each tap creates a timestamped entry in the session log with:
- Event name
- Timestamp (local time and elapsed time since session start)
- GPS coordinates at the moment of tap (if location access was granted)
Events can be tapped multiple times — for example, tapping "Touch & Go" on each circuit around the pattern. Each tap creates a separate log entry.
The elapsed time since the previous event is shown as a small delta below each log entry, giving you a quick interval reference without doing mental math.
Logging Maneuvers
Maneuvers are a separate, parallel log within a session — distinct from the main event log. They're intended for training flights where you want to record each maneuver practiced without cluttering the primary event sequence.
Tap the MANEUVER button at the bottom of the logging screen to open the maneuver picker. Select a maneuver to timestamp it. The default maneuver list includes approximately 16 entries covering common private, instrument, and commercial maneuvers:
| Category | Maneuvers |
|---|---|
| Basic | Steep Turns, Slow Flight, Ground Reference Maneuvers, Rectangular Course, S-Turns |
| Stalls | Power-Off Stall, Power-On Stall, Accelerated Stall |
| Emergency | Emergency Descent, Simulated Engine Failure, Forced Landing |
| Instrument | Unusual Attitude Recovery, Timed Turns, Rate Climbs / Descents |
| Pattern | Short-Field Takeoff, Soft-Field Takeoff, Short-Field Landing, Soft-Field Landing |
The maneuver list is fully customizable in Settings. You can add, rename, reorder, and
delete maneuvers. Custom maneuvers are saved to localStorage under
flight-timer-prefs.
GPS & Airport Resolution
When GPS is enabled (Settings → GPS On), the app records the device's latitude and longitude at the moment each event is tapped. Coordinates are stored with the session and included in OADS exports.
Airport resolution uses the bundled airports.json.gz dataset (~200 KB
gzipped), which contains approximately all public-use US airports. When the session
ends, the app finds the nearest airport to your first and last GPS-tagged events using
the haversine formula. If a match is found within 3 nautical miles, the airport identifier
is shown on the session card in the History view as origin and destination.
If GPS is disabled or location permission is denied, no coordinates are recorded. Session cards will show no airport identifiers. All other functionality is unaffected.
Ending a Session
Tap END FLIGHT at the bottom of the logging screen to close the session. A confirmation dialog appears — confirm to finalize. The session is marked complete, the wake lock is released, and you are taken to the Session Detail view.
If you close the app or navigate away without ending the session, the partial session is preserved in IndexedDB. When you reopen the app, you will be prompted to resume or discard the incomplete session.
Reviewing Sessions
The History screen lists all completed sessions in reverse chronological order. Each card shows:
- Date and start time
- Origin and destination airport identifiers (if GPS was active)
- Total session duration
- Template used
- Event count and maneuver count
Tap any card to open the Session Detail view.
Session Detail
The Session Detail view shows the complete event log in chronological order, with each entry's absolute time, elapsed time, delta from the previous event, and GPS coordinates (if recorded). Maneuvers logged during the session are shown in a separate section below the event log.
From the detail view you can:
- Export the session as JSON or OADS
- Edit any timestamp (see Editing Timestamps below)
- Delete the session (requires tap confirmation)
Editing Timestamps
Tap the time value on any event row in Session Detail to open the timestamp editor. You can adjust the time forward or backward using the spinner controls. The elapsed and delta values throughout the log update live as you adjust the time.
Edits are constrained so an event cannot be moved before the previous event or after the next event in the log — maintaining chronological order is enforced automatically.
Why Backup Matters
All session data is stored in IndexedDB on your device. This data is not synced to a server or cloud service. It can be lost if:
- You clear your browser's site data or storage
- The browser or OS prunes storage under low-disk-space pressure (especially on iOS)
- You switch to a different browser or device
- The app is uninstalled
Export JSON
Tap Export JSON in the Session Detail view or in the History screen's bulk
export menu to download a .json file containing the full session record.
The JSON format is the app's native format and preserves every field — event names,
timestamps, GPS coordinates, maneuver logs, template metadata, and session identifiers.
JSON exports can be re-imported into the app at any time via the Import function.
id Unique session UUID startedAt ISO 8601 timestamp endedAt ISO 8601 timestamp template Template name events Array of event entries maneuvers Array of maneuver entries origin Airport identifier or null destination Airport identifier or null
Export OADS
OADS (Open Aviation Data Standard) export produces a structured JSON file following
the OADS 1.0 track_log envelope. This format is designed for
interoperability with other aviation tools that support OADS.
The OADS export is generated via oads-convert.js, which maps the session's
event log to a GeoJSON LineString track (when GPS coordinates are present) along with
parallel property arrays for timestamps and metadata.
- Departure and destination are populated from resolved airport identifiers.
- When GPS data is present, the track geometry is a GeoJSON LineString using coordinates from each tapped event.
- App-specific fields (event names, template name, maneuver log) are stored in
extensions.flight-timer.
Import
Tap Import in the History screen to load a previously exported JSON file.
The app validates the file structure and, if valid, adds the sessions to IndexedDB.
Duplicate sessions (matching id) are skipped — importing the same file
twice does not create duplicate records.
Only the app's native JSON format is supported for import. OADS files exported from other tools are not currently supported for import.
Data Storage
| Store | Key / Name | Contents |
|---|---|---|
| IndexedDB | flight-timer-db v1store: sessions |
All session records — events, maneuvers, timestamps, GPS data |
| localStorage | flight-timer-templates |
Custom template definitions (JSON array) |
| localStorage | flight-timer-prefs |
User preferences: time format (12/24hr), GPS on/off, custom maneuver list |
All data is stored locally on your device. Nothing is transmitted to a server.
Airport Database
The bundled airport database (airports.json.gz) is a ~200 KB gzipped
dataset of US public-use airports. It is fetched and decompressed in-browser on first
session start, then cached by the service worker for all subsequent sessions.
Nearest-airport matching uses the haversine great-circle distance formula. An airport is considered a match if it falls within 3 nautical miles of the GPS coordinate recorded at session start (origin) or session end (destination). If no airport is within 3 nm, the field is left blank.
Offline & PWA
Flight Timer is a Progressive Web App. After the first load, the app shell, all JavaScript, CSS, and the airport database are cached by a service worker. All subsequent launches — including with no network — are served from the cache.
To install as a standalone app, use your browser's Add to Home Screen (iOS/Android) or Install (Chrome/Edge desktop) option. Once installed, the app launches directly without opening a browser tab.
About
Flight Timer is part of Aviator's Toolkit — a collection of offline-first aviation tools for general aviation pilots.
- Built with vanilla HTML, CSS, and JavaScript — no frameworks, no accounts, no server.
- Designed for cockpit usability: large tap targets, B612 aviation font, wake lock, offline-first PWA.
- Open Aviation Data Standard (OADS) export for long-term archival and interoperability.
Part of Aviator's Toolkit. Built by Cam Peterson at Parachute River.