-
Notifications
You must be signed in to change notification settings - Fork 0
Onboarding Flow
Implemented a comprehensive onboarding wizard system that guides new users through setting up their TrueHour. The wizard provides three pathways: manual entry, ForeFlight CSV import, and loading saved budgets.
Completed: 2025-11-29
The onboarding flow replaces the previous "blank screen" first-time user experience with a friendly, guided wizard that helps users:
- Import their existing flight hours (manually or via ForeFlight CSV)
- Set up their training aircraft with rental rates
- Select their certification goal
- Start using the calculator with confidence
- Three Entry Paths: Manual, ForeFlight Import, or Load Saved Budget
- Progressive Wizard: Multi-step guided flow with progress tracking
- Smart Defaults: Auto-detects aircraft from logbooks, suggests default selections
- FAA Verification: Optional aircraft data verification from FAA registry
- Validation: Inline validation prevents common data entry errors
- Resume Support: Can resume interrupted onboarding sessions
-
Classic Mode Fallback: Option to skip onboarding with
?flow=classic
For users without ForeFlight or starting fresh
Landing Screen β Enter Hours β Add Aircraft β Select Certification β Review β Main App
| | | | |
| | | | |
3 options Total, PIC, XC, Type, Reg, IR, CPL, CFI Summary of
Instrument Wet/Dry Rate + Training Pace all settings
Steps:
-
Enter Hours: Input total flight time, PIC, cross-country, instrument, and simulator hours
- Validation: PIC, XC, and Instrument cannot exceed Total
- All fields start at 0 for new pilots
-
Add Aircraft: Add one or more training aircraft
- Enter make, model, and tail number (optional)
- Choose wet rate (fuel included) or dry rate (fuel separate)
- For dry rate: enter fuel price and burn rate
- Can add multiple aircraft
- Form with "Save Aircraft" button and live aircraft list
-
Select Certification: Choose training goal
- Instrument Rating (Part 61)
- Commercial Pilot License (Part 61)
- Certified Flight Instructor
- Set training pace (lessons per week)
-
Review: Confirm all entered data
- Summary of hours
- List of aircraft with rates
- Certification goal
- Option to go back and edit
For users with ForeFlight logbook data
Landing Screen β Upload CSV β Import Aircraft β Verify Hours β Select Cert β Review β Main App
| | | | | |
| | | | | |
3 options Drop/Browse Select aircraft Auto-calculated IR/CPL/CFI Summary
CSV file + enter rates totals
Steps:
-
Upload CSV: Drop or browse for ForeFlight CSV export
- Automatic parsing of logbook data
- Progress indicator during processing
- Error messages if file format invalid
-
Import Aircraft: Select aircraft to import
- Shows all aircraft detected in logbook
- Displays total hours logged per aircraft
- FAA Verification: US aircraft (N-numbers) are automatically verified against FAA registry
- Data source badges: "β FAA Verified", "β FAA Cached", or "ForeFlight"
- Pre-filled year, make, and model from FAA data (or ForeFlight if not available)
- All fields editable
- Checkbox to select/deselect each aircraft
- Enter wet or dry rental rates for each
- Default aircraft checkbox (first selected by default)
- "Continue" button appears at bottom after selections made
-
Verify Hours: Review auto-calculated flight hours
- Total time, PIC, cross-country, instrument
- Checkbox: "These hours look correct"
- Must confirm before proceeding
-
Select Certification: Same as manual path
-
Review: Same as manual path, but shows imported data
For users returning to a previous budget
Landing Screen β Select File β Main App
| |
| |
3 options Browse for
saved JSON
Steps:
-
Select File: Upload previously saved budget JSON
- Drop or browse for .json file
- Loads all configuration: hours, aircraft, settings
- Bypasses all setup steps
- Goes directly to main calculator
The first screen users see, presenting three clear options:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β TrueHour β
β Plan your flight training costs with precision β
β β
β ββββββββββββββ ββββββββββββββ ββββββββββββββ β
β β π β β βοΈ β β πΎ β β
β β β β β β β β
β βStart Fresh β β Import β β Load β β
β β β β Logbook β β Budget β β
β β β β β β β β
β βEnter hours β βUpload CSV β βContinue β β
β βand goals β βto auto-fillβ βsaved work β β
β β manually β β β β β β
β ββββββββββββββ ββββββββββββββ ββββββββββββββ β
β β
β Try with sample data β’ Skip to classic view β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Features:
- Clear visual hierarchy
- Icon-based navigation
- Descriptive subtitles
- Sample data option for testing
- Classic mode escape hatch
Shows current position in the flow:
ββββββββββββββββ Step 2 of 4
- Visual progress indicator
- Step counter
- Updates as user advances
[β Back] [Continue β]
- Back button (hidden on first step)
- Continue button (changes to "Complete Setup" on last step)
- Hidden on auto-advance steps (CSV upload, aircraft import)
Contextual help messages appear on each step:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β π‘ Tip: These hours help us calculate how much β
β training you have left. PIC, XC, and Instrument β
β hours cannot exceed your total flight time. β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Real-time validation with helpful error messages:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β Validation Error: β
β β’ PIC hours cannot exceed total flight time β
β β’ Cross Country hours cannot exceed total time β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
New in this release: Automatic FAA registry verification for US aircraft during ForeFlight import.
- Detection: During CSV processing, identifies US aircraft (N-numbers)
- Lookup: Queries tail-lookup service (if available) for FAA data
- Enrichment: Updates aircraft with verified year, make, and model
- Visual Indicators: Shows data source badges
- β FAA Verified (green) - Fresh data from FAA registry
- β FAA Cached (blue) - Previously verified data from cache
- ForeFlight (gray) - Data from logbook only (no FAA verification)
- Accuracy: Ensures aircraft data matches official FAA records
- Consistency: Standardized make/model names
- Trust: Visual confirmation of data source
- Fallback: Uses ForeFlight data if FAA lookup unavailable
FAA verification requires the optional tail-lookup service:
# docker-compose.yml
services:
tail-lookup:
image: ryakel/tail-lookup:latest
# ... configurationIf not available, onboarding works normally with ForeFlight data only.
// Wizard collects data
wizardData = {
hours: {
total: 90,
pic: 40,
xc: 11.2,
instrument: 4.3,
simulator: 3.1
},
certification: 'ir',
lessonsPerWeek: 2
}
// Converts to global currentHours
currentHours = {
totalTime: 90,
picTime: 40,
picXC: 11.2,
instrumentTotal: 4.3,
simInstrumentTime: 3.1,
dualReceived: 50, // calculated: total - pic
actualInstrument: 0.86, // estimated split
simulatedInstrument: 3.44,
// ... additional fields
}
// Aircraft saved via AircraftAPI
AircraftAPI.addAircraft({
type: "Cessna 172",
registration: "N12345",
wetRate: 165,
fuelPrice: 6,
fuelBurn: 8,
source: "manual"
})// CSV parsed by parseForeFlight()
validFlights = [
{ Date: '2024-01-15', TotalTime: 1.5, PIC: 1.5, ... },
{ Date: '2024-01-20', TotalTime: 1.8, PIC: 0, ... },
// ... more flights
]
// processLogbookData() calculates totals
currentHours = {
totalTime: 90,
picTime: 40,
picXC: 11.2,
instrumentTotal: 4.3,
simInstrumentTime: 3.1,
batdTime: 2.5, // BATD simulator hours
// ... all fields calculated from logbook
}
// Detected aircraft
detectedAircraft = [
{
registration: "N12345",
make: "Cessna",
model: "172",
year: "1981",
totalTime: 45.5,
dataSource: "faa" // or "cache" or "foreflight"
},
// ... more aircraft
]
// User adds rates, saved via AircraftAPIapp/
βββ js/
β βββ onboarding.js # 1751 lines - Main wizard logic
β βββ aircraft-ui.js # Aircraft import modal integration
β βββ aircraft-api.js # Aircraft data management
β βββ aircraft-lookup.js # FAA verification service
βββ css/
β βββ styles.css # Wizard and landing styles
βββ index.html # Landing and wizard HTML
OnboardingManager (onboarding.js):
-
init()- Initialize onboarding system -
showLanding()- Display landing screen -
startManualPath()- Begin manual entry flow -
startForeFlightPath()- Begin ForeFlight import -
startLoadPath()- Begin load saved budget -
nextStep()- Advance to next wizard step -
previousStep()- Go back one step -
validateCurrentStep()- Validate current step data -
saveStepData()- Save current step to wizardData -
completeOnboarding()- Finish and show main app -
processLogbookData()- Parse ForeFlight CSV and calculate hours -
renderAircraftList()- Render aircraft import UI with FAA badges
AircraftLookup (aircraft-lookup.js):
-
isOnlineLookupEnabled()- Check if tail-lookup service available -
isUSAircraft(registration)- Check if N-number format -
lookupByTailNumber(tailNumber)- Query FAA data -
getCachedLookup(tailNumber)- Retrieve cached results
const OnboardingManager = {
currentPath: 'manual', // Current flow: manual/foreflight/load
currentStep: 'enter_hours', // Current wizard step
wizardData: { // Accumulated data
hours: {},
detectedAircraft: [],
csvAircraftData: [],
certification: '',
lessonsPerWeek: 2,
aircraftSaved: false // Prevent duplicate saves
},
_flightData: [], // Raw CSV flight data
_aircraftTableData: [] // Raw CSV aircraft table
}The wizard supports hash-based routing for bookmarking and back button:
#/onboarding β Landing screen
#/onboarding/manual/hours β Manual path, enter hours
#/onboarding/manual/aircraft β Manual path, add aircraft
#/onboarding/foreflight/upload β ForeFlight path, upload CSV
#/onboarding/foreflight/aircraft β ForeFlight path, import aircraft
// Onboarding completion flag
localStorage.setItem('flight-budget-onboarding-completed', 'true')
// In-progress wizard data (for resume)
localStorage.setItem('flight-budget-onboarding-progress', JSON.stringify({
path: 'manual',
step: 'add_aircraft',
data: { hours: {...}, ... }
}))- Total Time: Must be β₯ 0
- PIC: Cannot exceed Total Time
- Cross Country: Cannot exceed Total Time
- Instrument: Cannot exceed Total Time
- Simulator: Optional, no validation
- Make: Required (manual path)
- Model: Required (manual path)
- Registration: Optional
- Rate: Must have either wet rate OR dry rate > 0
- Fuel Data: Required only if using dry rate
- CSV Format: Must be valid ForeFlight export
- Aircraft Selection: At least one aircraft must be selected
- Rates: Each selected aircraft must have a rate entered
- Hours Confirmation: User must check "These hours look correct"
onError: (errorMessage) => {
// Display user-friendly error message
statusEl.innerHTML = 'β ' + errorMessage;
}Common Errors:
- Invalid file format (not a ForeFlight CSV)
- Missing required columns
- No valid flights found
- Corrupt or truncated file
- No rates entered: Alert prompts for rates before allowing import
- No aircraft selected: Cannot advance without selecting at least one
- Invalid rate values: Must be positive numbers
- Unsaved changes: Warns before navigating away
- Missing required data: Blocks advancement until validated
- Back button: Safely returns to previous step
When onboarding completes, all data is transferred to the main app:
completeOnboarding: function() {
// 1. Mark as completed
localStorage.setItem('flight-budget-onboarding-completed', 'true')
// 2. Clear progress data
localStorage.removeItem('flight-budget-onboarding-progress')
// 3. Hide wizard
document.getElementById('onboarding-wizard').style.display = 'none'
// 4. Show main app
this.showMainApp()
// 5. Trigger initial calculation
if (typeof updateDisplay === 'function') {
updateDisplay()
}
}Aircraft saved during onboarding are automatically rendered as cards in the main calculator:
const allAircraft = AircraftAPI.getAllAircraft()
allAircraft.forEach(ac => {
addAircraft({
id: ac.id,
make: ac.make,
model: ac.model,
registration: ac.registration,
type: ac.wetRate > 0 ? 'wet' : 'dry',
rate: ac.wetRate > 0 ? ac.wetRate : ac.dryRate,
fuelPrice: ac.fuelPrice,
fuelBurn: ac.fuelBurn
})
})Certification and training pace are set in the main app:
document.getElementById('targetCert').value = wizardData.certification
document.getElementById('lessonsPerWeek').value = wizardData.lessonsPerWeekUsers can bypass onboarding entirely by adding ?flow=classic to the URL:
http://localhost:8181/?flow=classic
Use Cases:
- Experienced users who know the interface
- Testing or development
- Quick access without setup
- Troubleshooting onboarding issues
Behavior:
- Skips landing screen
- Shows main app immediately
- No aircraft or hours pre-filled
- User manually configures everything
For testing and demos, users can click "Try with sample data":
loadSampleData: function() {
// Pre-fill with realistic sample data
currentHours = {
totalTime: 90,
picTime: 40,
picXC: 11.2,
instrumentTotal: 4.3,
// ...
}
// Add sample aircraft
AircraftAPI.addAircraft({
type: "Cessna 172",
wetRate: 165,
// ...
})
// Set sample certification
document.getElementById('targetCert').value = 'ir'
}- Resume Sessions: Auto-save and resume incomplete wizards
- More Certifications: Add PPL, Multi-Engine, ATP options
- Advanced Import: Support MyFlightBook, LogTen, other formats
- Bulk Editing: Edit multiple aircraft at once during import
- Rate Presets: Common rental rates by aircraft type
- Progress Save: Save wizard state for later completion
- Undo/Redo: Step back without losing data
- Tooltips: More detailed help for each field
- Video Tutorial: Embedded walkthrough video
- Import Validation: Warn about unusual data patterns
- Import from Google Sheets
- Support for international aircraft (non-N-numbers)
- Multi-instructor rate tracking
- Club vs rental aircraft modes
- Landing screen displays correctly
- Can enter valid hours
- Hours validation works (PIC β€ Total, etc.)
- Can add multiple aircraft
- Can select certification
- Review page shows correct data
- Completes successfully
- Main app populates correctly
- Can upload valid CSV
- Parsing completes without errors
- Aircraft detection works
- FAA verification runs (if service available)
- Data source badges display correctly
- Can select/deselect aircraft
- Can enter rates for each aircraft
- Can set default aircraft
- Hours verification shows correct totals
- Simulator hours calculate correctly
- Review page shows imported data
- Completes successfully
- Can upload valid JSON
- Loading completes without errors
- All data restored correctly
- Aircraft cards render
- Main app shows loaded state
- Empty states handled gracefully
- Invalid files show clear errors
- Back button works correctly
- Browser back/forward work
- URL routing works
- Classic mode bypass works
- Sample data loads correctly
- Multiple aircraft (10+) work
- Special characters in names handled
- Zero hours handled
- Very large hour values handled
- Progress bar updates
- Navigation buttons show/hide correctly
- Help tips display
- Validation messages clear
- Responsive on mobile
- Keyboard navigation works
- Focus management correct
-
No session persistence: Closing browser loses in-progress wizard
- Workaround: Complete wizard in one session
- Fix: Phase 2 will add auto-save
-
No edit after completion: Can't re-run wizard to change data
-
Workaround: Use main app settings or
?onboarding=true - Fix: Add "Edit Onboarding Data" button
-
Workaround: Use main app settings or
-
Limited file format support: Only ForeFlight CSV
- Workaround: Manually enter hours
- Fix: Phase 2 will add more formats
-
FAA lookup requires service: Works only if tail-lookup deployed
- Workaround: ForeFlight data used if unavailable
- Fix: Bundled offline FAA database option
- Quick Start Guide - Get started in 5 minutes
- Aircraft Management - Aircraft setup details
- Main README.md for overview
- See inline JSDoc comments in
onboarding.js - See integration points in
aircraft-ui.js - Check
app.jsfor data flow
Issue: BATD and simulator hours showed 0.0 even when present in ForeFlight CSV.
Root Causes:
- Wrong field name: Used
ac.EquipmentTypeinstead ofac['equipType (FAA)'] - Whitespace mismatch:
aircraftIdnot trimmed before map lookup
Fix:
- Changed line 1482 in onboarding.js:
equipType: ac['equipType (FAA)'] || ac['equipType'] || '' - Changed line 1499:
const aircraftId = (row.AircraftID || '').trim()
Result: Simulator detection now works correctly for BATD, AATD, and FTD equipment types.
Issue: In classic (non-wizard) flow, ForeFlight import saved aircraft to AircraftAPI but didn't create DOM cards, so budget calculator couldn't auto-fill hours.
Root Cause: showCSVImportModal function saved aircraft but didn't call addAircraft() to create cards.
Fix: Added lines 965-992 in aircraft-ui.js to iterate through imported aircraft and create DOM cards.
Result: Both wizard and classic flows now correctly render aircraft cards after import.
This feature is licensed under the MIT License along with the rest of the project.
Copyright (c) 2024-2025 FliteAxis
- β Initial onboarding wizard implementation
- β Three-path flow: manual, ForeFlight, load saved
- β Landing screen with clear options
- β Multi-step wizard with progress tracking
- β Hours entry with validation
- β Aircraft import from ForeFlight CSV
- β FAA aircraft verification integration
- β Data source badges (FAA Verified, Cached, ForeFlight)
- β Certification selection
- β Review and confirmation step
- β Classic mode bypass option
- β Sample data for testing
- β URL routing and bookmarking
- β Fixed simulator hour calculation bug
- β Fixed classic flow aircraft card rendering bug
Status: β Complete and ready for production Next Step: Update main README and deploy Documentation: Complete License: MIT License
π View on GitHub | π³ Docker Hub
π Report Issue | π¬ Discussions
License: MIT License | Copyright (c) 2024-2025 FliteAxis
π Getting Started
π¦ Deployment
π§ Development
π Security
- Security Setup Guide
- Security CI/CD Pipeline
- Code Quality & Linting
- SBOM Management
- Vulnerability Scanning
π Dependencies
π³ Docker
π Reference
π Links