The source repository is a Git repo hosted on SourceForge and is publicly available at
https://sourceforge.net/projects/pohperformance/. SourceForge was chosen because it's free and can handle the large airport database files without requiring special Git LFS handling like GitHub.
The source repository contains the source for:
The repository contents will allow a developer to:
The contents of this repository are copyrighted and require a license to make derivative works.
The license is free for personal use.
However, you may not distribute it or make it publicly available.
The license is also free for non-commercial distribution, but it has strict conditions, including creating distinctive graphics.
All licensees must indemnify POH Performance LLC and its contributors against
all claims arising from the use of the modified app.
POH Performance LLC and its contributors cannot be held liable for
modifications they haven't vetted.
Please contact info@pohperformance.com for more information or to acquire a license.
Android and iOS versions of the apps are created by using Apache Cordova.
The Source repository does not include the Makefiles to build and submit native iOS and
Android apps, as this process involves private keys and certificates.
However, the source repository contains the config.xml files Cordova requires.
In general, POH Performance apps use the following criteria for client-side technology:
Server-side technology is only limited by server capabilities. The POH Performance server is currently hosted on a Godaddy.com Web Hosting Plus shared host. The server is preconfigured to use Apache as the server framework and does not support NodeJS.
The NodeJS scripts require some node libraries to be installed. See the Scripts Reference.
The app development and deployment process may rely on the following software:
.psd files are recorded in the source/image/<appName>/ directories. Typically, an aircraft top-view is derived from a top-view image in a POH and then edited in Photoshop. The top-view image is displayed on the takeoff and landing runway diagrams. The top-view image and a favicon are the only images required for a Web-only deployment.All clients are fundamentally WebApps. They may be deployed on desktop devices, but they may also be used on mobile devices for personal use outside of the app store distribution. The WebApp is a Progressive WebApp (PWA) that can be installed on a mobile device's home screen and can operate offline after installation and initial open.
The WebApp also contains a Service Worker that caches app source files but forwards server API requests to the network when connected. The WebApp build process inserts a manifest of all files (other than the Service Worker) into the index.html file. When connected, the index.html file is always fetched from the server, bypassing local or network caching. The Service Worker will preload all files in the manifest into the application cache whenever a different index.html file is fetched from the server.
The files in the manifest have a unique element in the path name for each build. This ensures that only the files associated with the current version of index.html are placed in the cache. Any caching in the client or network will be ignored.
The WebApp Service Worker is disabled when using Cordova to avoid violating app store policies against loading code.
The build process is run by a main Makefile in the project root directory. Run make with no arguments to build every app. It has the following targets:
buildweb and cdv images of every app. This is the default target.checkMdLinkscheckMdLinks.js on every Markdown file in doc/ to report broken links and anchors. It checks every file, then fails if any had errors.cleanbuild/ directory.clobberclean and imageClean targets.dbdocdoc/ into HTML files in build/doc. See Building the documentation.docCleanbuild/doc.imageimageCleanlineCountlineCountFullbrew install scc).linttmlLint.js to check the state variables the templates reference. Each file's lint output is kept in build/lint so that only changed files are re-linted. The lint output is not part of the app builds, so run this before committing.lintCleanbuild/lint so that all files will be re-linted the next time lint is made.modelStatspubDbpubDbTestpubDoccheckMdLinks, and if it finds no broken links or anchors, publish the documentation to the developer section of the production web site, pohperformance.com:/developer/doc/V5 (override with DOC_REMOTE). Only the pages built from the current Markdown files are published; any other file there, such as the page of a removed document, is deleted. Set WEBPUB_DRY_RUN=1 to preview the changes.servetestselfTestRun.js. Every app is run, then the target fails if any app failed. See Unit tests.webbuild/web. The images can be directly transferred to a web server.webpubtestWEBPUB_DRY_RUN=1 to preview the upload.Any of the app targets can also be made for a single app as make <appId>.<target>, for example make C172.web. Some targets exist only in that form:
<appId>.cdvbuild/cdv. The native apps are built from these images in the private release repository, which is not part of this repository.<appId>.test<appId>.webpubtest<appId>.db, <appId>.pubDb, <appId>.pubDbTest, <appId>.lint, <appId>.image, <appId>.imageClean, <appId>.cleanThe root Makefile invokes sub-makefiles for the app targets. If a sub-makefile of the form <appId>.mk exists (Testapp.mk, Radar.mk, Example1.mk), it will use that to build the target. Otherwise, it will use app.mk.
The icons, favicons, and splash screens are all automatically generated. See Icon and splash screen generation. The splash screens may contain an optional logo image which must be generated by hand.
The aircraft apps require an aircraft top view image to use on the takeoff and landing runway diagrams, which is also used on the splash screens. This is typically cropped from the POH or other sources and adjusted for clarity using tools like Photoshop.
The app store icons are typically generated using the icon generation scripts. App images for the app stores are normally taken by running device simulators for different-sized devices in Xcode and Android Studio.
Apps that require an airport database must be added to the aircraftApps in the main Makefile. This will ensure that databases for them will be built.
The airport database is built by combining the airport data from the NFDC and ourairports.com. See the Airport Database Reference. The bulk of the work is done using the buildAirportDB.js script.
The database is built by running make db in the project root directory. When make db is run, it does the following:
nasrCycle.js, and extracts APT_BASE.csv, APT_RWY.csv, and APT_RWY_END.csv to source/airportData/NFDC/. The EFF_DATE column on every row is moved to EFF_DATE.txt so that a cycle's diff shows only the data that changed. Before extracting, it checks that the zip's EFF_DATE is the requested cycle and stops if it isn't, leaving the current NFDC files in place. After all the downloads, it prints the NFDC data's effective date and the next cycle's effective date. Set NFDC_CYCLE (e.g. NFDC_CYCLE=01_Oct_2026) to fetch the next cycle's preview, or import a zip downloaded by hand with make nfdcImport NFDC_ZIP=<zip>.airports.csv and runways.csv files from ourairports.com to the source/airportData/ourairportscom/ directory.stations.cache.xml.gz file from aviationweather.gov and unzips it to source/airportData/stations.xml.source/airportData/dbFlags/<appId>.txt file containing this app's unique flags.tools/buildAirportDB.js passing the retrieved flags and directing the log output to source/airportData/logs/<appId>_log.txt. The results are the app's built-in database buildStamp/internalData/airportData.js and the downloadable copy in externalData/. Both are checked into git.Use the source/airportData/dbFlags/<appId>.txt to specify the runway requirements that are unique to the aircraft. For example, to ensure that the included runways are long enough for any aircraft of that type to takeoff or land even under the best conditions. The log files help answer questions about why a conflicting code was dropped or why an airport was dropped because it did not have runways compatible with the aircraft.
The V5 apps check the web site for an updated database: they fetch airportDataTimestamp.json from the app's directory and, if its version or timestamp differs from the installed database, download airportData.json. V4 apps have no downloadable database. To send a new database to the apps without publishing a new app version, run make pubDb for the production web site or make pubDbTest for the test site, or make <appId>.pubDb and make <appId>.pubDbTest for one app. These upload only the app's externalData/airportData.json and airportDataTimestamp.json, with rclone, to the same sites as the web image publishers. Before uploading, they check that the database parses and that the timestamp file matches it. The database is uploaded first and the timestamp last, so an app never sees a new timestamp before the database it describes. Any timestamp change triggers a download, even to an older database, so pubDb refuses to publish a database that differs from the committed one; pubDbTest publishes the working copy. Set WEBPUB_DRY_RUN=1 to preview the uploads.
The Testapp is a standalone app designed to help test and debug MVCS and other infrastructure code. It runs unit tests and has pages to exersize various common functions.
Almost all testing and debugging use the WebApp form of an app. Running make serve builds every app and starts a development server on http://localhost:8000 whose index page links to each app. Use the browser's debugger as required. The server watches source/ and rebuilds the documentation, lint and web images whenever a file changes, then reloads the browser. If lint reports errors, the app's page shows the lint output instead of the app until they are fixed.
make serve needs PHP (it runs php -S with a router that stands in for the production .htaccess rewrites, so the server API works locally), fswatch to watch for changes, and browser-sync from node_modules. It refuses to start if another instance is already running or port 8000 is in use. The server's saved-input, log and trouble-report files are kept under localServer/.
The Settings page has a hidden card for developers. You can view the card by entering XYZZY (look it up) in the password field. The card contains the following:
Test button that opens the Test page and runs any built-in unit tests.XYZZY into the password field.Load button to allow you to load a trouble report into the appJSON dump button that will mail the app state to the email address on the Settings page.JSON restore button presents a dialog that allows you to paste edited JSON to use to restore the app state.Most apps have built-in unit tests. Pressing the Test button in the Settings page developer card will open the Test page and run all built-in unit tests. Tests are defined using unitTest. Aircraft apps typically have the following tests:
The test page will display failed test result. Selecting Show detailed results will display all results, both passed and failed.
The same tests can be run without a browser window. make test builds every app that has a self-test suite and runs each suite in headless Chrome. make <appId>.test does the same for one app:
make C172.test
Each run prints a JSON summary of any failing groups, followed by <appId>: PASS or <appId>: FAIL. A run fails on any failing test and also on any app assert() failure, which the in-app Test page does not count. Testapp and Example1 have no self-test page and are not included, so the Testapp infrastructure tests must still be run in a browser.
The Testapp is an internal WebApp specifically for testing the MVCS infrastructure. It contains pages that test UI elements, the infrastructure for common pages, and infrastructure unit tests.
Users can press the Email button in the Settings page "Questions or feedback" row to send email to the webmaster at info@pohperformance.com using their local email app.
Users may also file a Trouble Report (TR) by pressing the Send button on the "Trouble report" row. Trouble reports record all app state variables at the time of the report and include a user message. Each TR has an ID string that begins with "TR-". The ID contains some random digits that would make it difficult to guess. The reports are stored on the server and a notification is sent to the webmaster at info@pohperformance.com. A reminder notification is sent daily until the TR is archived.
A TR may be retrieved by pressing the Trouble Report "Load" button and entering the Trouble Report ID. This will set the app's input state variables according to the TR data allowing you to see the user's exact setup. Once the problem is determined, the TR can be archived by pressing the Trouble Report "Archive" button.
The documentation is written in Markdown under doc/. make doc converts it to HTML in build/doc/, using the scripts described in the Scripts Reference. Open build/doc/index.html to read it. make serve also rebuilds the documentation whenever a file changes.
make doc edits the Markdown sources as well as generating HTML:
<!-- toc start --> and <!-- toc end --> markers by mdToc.js. Add a heading and the next build adds it to the table of contents.doc/mvcs/mvcs_index.md, the alphabetic and category index of the MVCS documents, is regenerated from the <!-- index="..." --> comments in the files by mdToIndex.js.Commit these generated changes with the documentation edits that caused them.
make checkMdLinks reports links and anchors that don't resolve. Run it after editing a document. It runs make doc first, so the tables of contents it checks against are current.