factcircuit
FactCircuit: an auditable claim-and-evidence verification loop with immutable provenance, staged checks, bounded retrieval, and reproducible evaluation.
Every well-documented UFO/UAP encounter on a 3D globe, with replayable flight paths, the official U.S. files and footage, and the tools to check each sighting yourself.
DataJavaScript · CSSGitHub @domw99OnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
Every well-documented UFO/UAP encounter on a 3D globe: flight paths, Blue Book, GEIPAN & MUFON files, 22k searchable journal pages, sighting checks. No keys.
Translation pending
Taken from the repository README
Loading the full README. The saved excerpt is shown below.
It runs in your browser with nothing to install and no sign-up or API keys.
God's Eye // UAP puts every well-documented UFO/UAP encounter on a 3D globe. You can replay each one along a reconstructed flight path, read the official U.S. and French files, search 22,000 pages of the MUFON, APRO, NICAP and CUFOS journals, and watch the footage. You can also check the ordinary explanations yourself: what was in the sky, the weather, military airspace and rocket launches.Read the full README ↗It runs in your browser with nothing to install and no sign-up or API keys.
Open it in your language: English · Español · Français · Deutsch · Português · Italiano · Nederlands · Polski · Türkçe · Русский · العربية · हिन्दी · Bahasa Indonesia · 日本語 · 한국어 · 中文
made by domw99
Features · Quick start · How it works · Open data · Data sources · Reading it honestly · Contributing
God's Eye // UAP puts every well-documented UFO/UAP encounter on a 3D globe. You can replay each one along a reconstructed flight path, read the official U.S. and French files, search 22,000 pages of the MUFON, APRO, NICAP and CUFOS journals, and watch the footage. You can also check the ordinary explanations yourself: what was in the sky, the weather, military airspace and rocket launches. Beside the Earth is the Moon (EARTH | MOON in the top bar), a globe of it in the same layout with its landing sites and the lunar reports. It is a UAP-only edition of Bilawal Sidhu's God's Eye View.
USS Nimitz "Tic Tac", 2004. From the globe of cases into the encounter off San Diego: the flight paths replay as the view circles, then it switches to night vision. ▶ Watch the 22-second video (MP4)
| 261 curated case files1561 → 2026, 47 countries and territories | 174 official U.S. releasesAARO / PURSUE footage via DVIDS | 10,096 Project Blue Book filesUSAF scans, 1947–1969, on the map | 2,768 GEIPAN filesFrance's official cases, graded A–D |
| 485 MUFON Journal issues1967–2008 · 2,517 report places mapped | 873 research journal issuesAPRO · NICAP · CUFOS · MUFON chapters | 22,000 journal pagesfull-text searchable in the app | 80,332 civilian reportsNUFORC, as a density layer |
Betty and Barney Hill, 1961. The car's route and the craft's reported path replayed over the White Mountains, cycling through Normal → NVG → FLIR → Ironbow.
There are seven sensor looks, rendered as real-time post-processing shaders (keys 1–7). They keep the picture sharp at any zoom, so markers and labels stay readable; the look comes from tone, grain and scanlines, not blur:
3D buildings are free, and off until you want them. Turn on OpenStreetMap buildings (via OpenFreeMap) under MAP or in the layer list, and they appear as you zoom into any town; Fly to ground view on a case turns them on for you. If you want Google's photorealistic 3D tiles instead, paste your own key under MAP.
New in 1.1: a real star sky and city lights, day and night lighting, four map styles, and NASA's picture of a case's day from orbit. ▶ Watch the 21-second video (MP4)
Map style (MAP or M): Satellite, Dark, Streets or Topographic, all keyless. Over the satellite map you can add place names and borders, which fade out close in where 3D buildings take over.
Lighting: Auto lights an open case by the sun at the moment it happened, with city lights on the night side; Day and Night hold that look everywhere; Off, where a first visit starts, keeps the globe evenly lit. The four-button switch in the top bar (☀ auto, day, night, off) changes it in one click, without opening any settings.
Hide the years bar (HIDE on the bar, or Y) for more room; the panels grow into the space, the choice is remembered, and ▲ YEARS brings it back.
Earthquakes (new in 1.2): the last 24 hours from the USGS, sized and coloured by magnitude. Strong quakes are sometimes reported as booms or odd lights, so it helps check a same-day sighting.
Fireballs (new in 2.0): the 888 bright meteors that U.S. government sensors have recorded since 1988 (NASA CNEOS), drawn as comets sized by energy, with the year bar filtering them. A fireball outshines the Moon for a few seconds, so it is a familiar cause of "a light that crossed the sky and went out". Press B to turn the view north up and P to tilt it; the compass turns with the view.
A symbol for every layer: rings for cases, diamonds for official releases, triangles for your own sightings, and a file, shield, hexagon, open book, spark and seismograph for Blue Book, GEIPAN, MUFON, the research archives, civilian reports and earthquakes, so you can tell the dots apart at a glance.
What did I see? (E) Enter a time, place, direction and how it moved. The app ranks the ordinary explanations it can test:
Live flights need a server, so aircraft elsewhere are listed as not checkable. Above, a bright, still light low in the WSW at dusk comes back as Venus; a coloured glow over North Dakota at midnight on 14 March 1989 comes back as the aurora of the great storm (Kp 8-).
The sky at that moment, for every case: Sun, Moon phase, planets and bright stars. Objects named in the official explanation are circled. For the Hills in 1961, Jupiter sits low in the SSW beside the Moon, just as the Air Force file says.
Historical weather since 1940 (ERA5): cloud layers, wind at 10 m and 100 m, and whether a slow object moved with the wind.
That day from orbit, for cases since 2000: NASA's true-colour picture of the whole Earth that day (MODIS on the Terra satellite) laid over the globe. Below, O'Hare on 7 November 2006 under the solid overcast the witnesses described.
Military airspace: which FAA restricted or warning areas a case falls in.
Geomagnetic activity, for every case since 1932: the Kp index for the three hours of the case (GFZ Potsdam), NOAA's storm scale, and whether an aurora could have been seen from there (it needs a dark sky and a latitude the auroral oval reaches at that Kp). It is a classic cause of strange lights at low latitudes.
Bright fireballs nearby, for every case since 1988: any fireball in NASA's record within 600 km and 3 hours, with how long before or after, how far and in which direction. The record holds only the bigger events, so an empty answer does not rule one out.
Nearest airfields: the closest airports and military fields, with the distance and direction, and a note that aircraft on approach (landing lights, apparently hanging still) are a common cause of reports near them. The list is of airfields as they are today, and says so.
GEIPAN is the UAP office of CNES, the French space agency, and the longest-running government UAP office in the world (since 1977, first as GEPAN). It has published its case files since 2007. The GEIPAN layer (blue) puts all 2,768 cases from its published files (1937–2018) on the map:
MUFON and The Black Vault released the Mutual UFO Network's journal free as "The MUFON Archive". The app brings it onto the map:
Space & Moon (SPACE & MOON in the top bar, or K) collects reports from beyond the atmosphere, 18 in all, each with what was reported, what is documented and the best explanation, and with its sources.
The pins are placed by a mapping fitted to known craters on the photograph (Gregory H. Revera, CC BY-SA 3.0), so they are accurate to about a degree. Every report has its own link (#/space/<id>), and ⧉ COPY LINK on a card copies it.
New in 1.3 and 1.4: the Moon beside the Earth, Space & Moon, and 10 more cases. ▶ Watch the 34-second video (MP4)
EARTH | MOON at the left of the top bar (or U) switches between the two worlds, and the Moon is laid out like the Earth: the same top bar, the list of places on the left with search, layers and sorting, a dossier on the right, the HUD, the zoom and reset controls, and the same sensor looks and lighting. It also opens from the Moon tab of Space & Moon, or with a link: #/moon, or #/moon/<place or report> such as #/moon/apollo-17 or #/moon/tycho.
The first visit on a phone says the app has more room on a computer (once). On phones and tablets the buttons are sized for a finger, and the layout holds up with the phone held sideways (the top bar keeps to two rows). Playing a flight path clears the screen down to the globe and a slim playback bar (DETAILS brings the panels back), the phone's Back button closes an open dialog, and the on-screen keyboard no longer covers the field you are typing in.
New in 1.2: Noir and Snow looks, lighting in the top bar, a hideable years bar, 16 languages, live earthquakes and 12 more cases. ▶ Watch the 23-second video (MP4)
Save it as an app: on a phone, ⤓ INSTALL APP in the top bar installs it in one tap where the browser allows it, and otherwise shows the exact steps for your browser (Share → Add to Home Screen on iPhone, the ⋮ menu on Android). It opens full screen, respects the notch and the home bar, reopens quickly, and works offline for what you have already looked at. Press and hold the icon for shortcuts: a random case, WHAT DID I SEE?, the official files and the Moon. The globe only draws when something changes and matches its sharpness to the device, so it stays smooth and easy on the battery. Phones get a lighter copy of the star sky. If your system is set to reduce motion, the camera cuts instead of flying.
Your language. A link can open in a chosen language by adding ?lang= and a code, for example ?lang=es. The picker in the top bar switches the whole interface between English, Español, Français, Deutsch, Português, Italiano, Nederlands, Polski, Türkçe, Русский, العربية (right to left), हिन्दी, Bahasa Indonesia, 日本語, 한국어 and 中文. It starts in your browser's language and remembers your choice. Buttons, labels, filters, the sky, weather and launch lines, and the messages are translated; the case texts, archive descriptions and quotations stay as published, so the evidence is never paraphrased. To add or improve a language, edit one file in src/i18n/locales/ (keys are the English texts); a test checks that every language covers every text the code asks for.
Also included:
git clone https://github.com/domw99/Gods-Eye-UAPs.git
cd Gods-Eye-UAPs
npm ci
npm run dev # http://localhost:5173
That's it. Nothing needs a key: the imagery, terrain, 3D buildings, weather, launches, satellites and place search all use free, keyless services.
In the app, click MAP (or press M) and paste a Google Maps Platform key with the Map Tiles API enabled. The key stays in that browser's localStorage and is sent only to tile.googleapis.com. You can remove it there at any time.
If you host your own copy, you can build keys in instead: copy .env.example to .env.
| Key | What it adds |
|---|---|
VITE_GOOGLE_MAPS_API_KEY | Google Photorealistic 3D Tiles for every visitor (Map Tiles API) |
VITE_CESIUM_ION_TOKEN | Cesium World Terrain, plus Google 3D Tiles through ion |
Restrict browser keys to your domain, because anything built into the site is public.
| Key | Action | Key | Action |
|---|---|---|---|
| 1–7 | Sensor modes (…, Noir, Snow) | E | What did I see? |
| / | Search | V | Witness view (during playback) |
| [ ] | Previous / next case | M | Map: style, place names, lighting, 3D |
| Space | Play / pause the flight path | G | Files library (government + MUFON) |
| T | Guided tour | L | Log a sighting |
| R | Reset view (whole globe, north up) | + − | Zoom toward the centre |
| N | Near me | S | Statistics |
| B | North up (turn the view so north is at the top) | P | Tilt the view, or look straight down again |
| K | Space & Moon | U | Switch between the Earth and the Moon (on the Moon: arrows turn, + − zoom, 0 reset, N names) |
| C | Group nearby markers on / off | Esc | Close, or back to the previous dialog |
| H | Hide the HUD | Browser Back | The record you had open before |
| Y | Hide / show the years bar | ` | Show the frame rate |
| D | Lighting: off (the start) → auto → day → night | F | Clean view: hide every panel |
| O | Orbit the middle of the screen; from far out, turn the Earth | ← ↑ → ↓ | Fly the camera (Shift: turn and tilt) |
| years bar (focused) | ← → move the range · Shift later end · Alt earlier end · PageUp PageDown ten years | Esc | Clear the range |
| Link | Opens |
|---|---|
#/case/nimitz-tic-tac-2004 | A curated case |
#/official/1007777 | An official release (DVIDS id) |
#/bluebook/1952-07-7273984-Tremonton-Utah-1377- | A Blue Book file |
#/geipan/1981-01-00849 | A GEIPAN file (Trans-en-Provence) |
#/mufon/2002_05/1 | A MUFON Journal page (issue, page index) |
#/journal/AFU_19711100_APRO_Bulletin_November-December/0 | A research-archive page (APRO Bulletin, Nov–Dec 1971) |
#/near/33.3943,-104.5230/Roswell | Everything reported near a place |
?mode=nvg | Start in a sensor mode |
?layers=bluebook,geipan,mufon | Start with extra layers on |
?view=-104.5,33.7,25000,0,-35 | Start at a camera position (lon, lat, height m, heading°, pitch°) |
It is a static site with no backend. Datasets are built by scripts ahead of time and shipped as JSON. Everything live is fetched straight from keyless public APIs in the browser, and the sky and satellite positions are computed on the device.
flowchart LR
subgraph build["Build time: scripts/ and weekly CI"]
direction TB
DVIDS["DVIDS / AARO<br/>official releases"] --> S1["sync-dvids.mjs"]
IA["Internet Archive<br/>Blue Book scans"] --> S2["build-bluebook.mjs"]
FAA["FAA special-use<br/>airspace"] --> S3["build-airspace.mjs"]
NUF["NUFORC<br/>(geocoded)"] --> S4["build-nuforc.mjs"]
KP["GFZ Potsdam<br/>Kp index"] --> S8["build-kp.mjs"]
FB["NASA CNEOS<br/>fireballs"] --> S10["build-fireballs.mjs"]
OA["OurAirports<br/>airfields"] --> S9["build-airfields.mjs"]
MUF["MUFON Journal<br/>OCR (Internet Archive)"] --> S5["build-mufon.mjs"]
GEI["GEIPAN<br/>published CSV"] --> S6["build-geipan.mjs"]
ARC["APRO · NICAP · CUFOS<br/>OCR (Internet Archive)"] --> S7["build-journals.mjs"]
S5 & S7 --> S11["build-textindex.mjs"]
end
S1 & S2 & S3 & S4 & S5 & S6 & S7 & S8 & S9 & S10 & S11 --> DATA[("public/data/*.json")]
CASES["src/data/cases/*.js<br/>261 curated cases"] --> APP
DATA --> APP["<b>Browser app</b><br/>Vite · CesiumJS<br/>astronomy-engine<br/>satellite.js"]
LIVE["<b>Live, keyless APIs</b><br/>Esri imagery · terrain<br/>OpenFreeMap buildings<br/>CelesTrak TLEs<br/>Launch Library 2<br/>USGS earthquakes<br/>Open-Meteo weather<br/>Wikipedia · Photon"] --> APP
Built to stay quick. The globe draws only when something changes, and a still globe redraws every 2 s. It starts without waiting for the imagery's service description (the loading screen clears about 40% sooner in local tests), asks the map servers for up to 18 tiles at a time, and uses coarser tiles while the camera moves. Markers and labels keep their GPU buffers when they change: with every layer on, a search uploads about 3 MB instead of 35 MB. Repeat visits load Cesium and the data from the offline cache without rewriting it.
| Layer | Code |
|---|---|
| Globe, imagery, terrain, 3D tiles, key handling | src/app/viewer.js |
| Rendering on demand, device quality, dynamic resolution | src/app/quality.js |
| Map styles and place names; centred zoom-out; keyboard flying and orbit | src/app/basemap.js, src/app/zoom.js, src/app/flycam.js |
| NVG / FLIR / Ironbow / CRT / Noir / Snow shaders | src/app/effects.js |
Interface languages (t(), dictionaries loaded on demand, right-to-left) | src/i18n/index.js, src/i18n/locales/*.js |
| Save to the home screen (one-tap install, steps per browser) | src/app/install.js |
| Case markers, flight paths & playback, witness view | src/layers/items.js, src/layers/tracks.js |
| Label decluttering; Blue Book, GEIPAN, MUFON, research-archive, NUFORC & earthquake points, satellites, launches, airspace, buildings | src/layers/*.js |
| Sky, weather, launches, airspace, GEIPAN classes, journal pages and full-text search, sighting-checker scoring | src/services/*.js |
| Dossier, list, timeline, modals, sky chart, story mode, statistics, share cards, Space & Moon | src/ui/*.js |
| Space & Moon entries and the Moon picture; "similar cases" ranking | src/data/space.js, public/space/, src/data/similar.js |
| The Moon: places, landing sites and their times, the globe on the Moon's ellipsoid, the Sun's position on it, the Earth-style layout | src/data/moon.js, src/app/moonglobe.js, src/app/moonsun.js, src/ui/moonview.js, public/space/moon-wac-2k.jpg |
src/
app/ viewer.js (globe, imagery, terrain, 3D tiles, star sky) · effects.js (NVG/FLIR/CRT shaders)
quality.js (render on demand, device quality) · horizon.js (markers hidden behind the Earth)
basemap.js (map styles, place names) · zoom.js (centred zoom-out) · flycam.js (keys, orbit)
data/ cases/ (curated case files) · govFiles.js · regions.js · taxonomy.js · items.js
layers/ items.js (case & release markers) · tracks.js (flight paths + playback) · billboard-buffers.js (markers keep their GPU buffers)
points.js (Blue Book / GEIPAN / MUFON / NUFORC) · satellites.js (live SGP4)
buildings.js (keyless OpenStreetMap 3D buildings) · launches.js (launch pads)
airspace.js (military airspace volumes) · declutter.js (label overlap)
services/ wiki.js (Wikipedia summaries, Commons media) · sky.js (planets, Moon, stars) · places.js (place search)
launches.js (Launch Library 2) · weather.js (Open-Meteo) · airspace.js (FAA SUA)
geomagnetic.js (Kp, aurora) · airfields.js (nearest airfields) · fireballs.js (NASA fireballs)
explain.js (sighting checker scoring) · mufon.js (MUFON Journal issues & page text)
geipan.js (GEIPAN classes, dates, links) · journals.js (APRO, NICAP, CUFOS)
textsearch.js (journal full-text search)
ui/ list.js · dossier.js · timeline.js · modals.js · skychart.js · story.js
stats.js (statistics charts) · sharecard.js (share images)
scripts/ sync-dvids.mjs · build-bluebook.mjs · build-nuforc.mjs · build-airspace.mjs
build-kp.mjs · build-fireballs.mjs · build-airfields.mjs · mcp-server.mjs (MCP server for AI assistants)
build-mufon.mjs · build-geipan.mjs · build-journals.mjs · build-textindex.mjs
build-cards.mjs (case preview images) · indexnow.mjs (search engines) · archive-pages.mjs (Wayback Machine)
build-skybox.py (NASA star map → sky box)
verify-media.mjs · check-links.mjs · fix-cesium-base.mjs
lib/ (GeoNames gazetteer · page-shell.mjs: the frame the static pages share · case-pages.mjs: a page per case, the case index + sitemap · browse-pages.mjs: the pages by country, decade, status and more · open-data.mjs: JSON, CSV, GeoJSON · llms.mjs: robots.txt, llms.txt, llms-full.txt; all made at build)
public/cards/ the preview image for each case page
tests/ Vitest suites · e2e/ Playwright browser tests
docs/ KNOWN-ISSUES.md (limits of the app and the data) · MCP.md (the AI-assistant server) · media/ (README pictures and videos)
AGENTS.md the developer guide (commands, conventions, releases); CLAUDE.md points to it
CONTRIBUTING.md · SECURITY.md · CODE_OF_CONDUCT.md · CHANGELOG.md · DATA_SOURCES.md · THIRD_PARTY_NOTICES.md
The 261 case files are free to reuse, under the same MIT licence as the code, from the open data page:
| File | What's in it |
|---|---|
cases.json | Every field: date and place with coordinates, category, evidence, status and explanation, summary, timeline, sources, and the 70 reconstructed flight paths with what each is based on |
cases.csv | One row per case, for spreadsheets |
cases.geojson | A point per case and a 3D line per flight path, for GIS tools and web maps |
They are made from src/data/cases/ on every build, with the page describing them as a schema.org Dataset so dataset search engines can find it. There is also a plain list of all case files, with no 3D globe needed, and pages that browse them by country, decade, status, kind of encounter, evidence and shape.
For AI assistants: llms.txt and llms-full.txt describe the site and give every case as plain text, and npm run mcp starts a local Model Context Protocol server (no network, no dependencies) with tools to search the cases (and count them by status, country, decade, evidence or shape), read one, find the cases near a place, list a date's, check for a bright fireball near a sighting and make a link to the globe. See docs/MCP.md for Claude Code and Claude Desktop.
All datasets ship in public/data/ and are rebuilt by scripts:
| Command | Source | Output |
|---|---|---|
npm run sync:official | DVIDS search, then each asset page (title, date, description, duration, thumbnail). Regions are resolved by src/data/regions.js. Runs weekly in CI. | official-uap-media.json |
npm run build:bluebook | Internet Archive collection project-blue-book, geocoded offline with GeoNames cities1000 | bluebook.json |
npm run build:airspace | FAA special-use airspace (ArcGIS open data), simplified | airspace.json |
npm run build:kp | The Kp geomagnetic index every three hours since 1932 from GFZ Potsdam (CC BY 4.0), packed one character per interval | kp.json |
npm run build:fireballs | NASA/JPL CNEOS fireball data API (U.S. government data, public domain): bright meteors since 1988 with a position, packed as compact events | fireballs.json |
npm run build:airfields | OurAirports (public domain): large and medium airports, small ones with an ICAO code or flights, and military fields by name | airfields.json |
npm run build:nuforc | planetsig/ufo-reports (geocoded NUFORC), facts only with the narratives removed | nuforc.json |
npm run build:mufon | The MUFON Archive on the Internet Archive (). It reads each issue's OCR text page by page, finds "Town, State" places in sighting reports (skipping addresses, meetings and hometowns), geocodes them with GeoNames and matches pages to curated cases. Only places, page numbers and short quotes are stored. |
Adding a case:
src/data/cases/*.js. Track points are p(lat, lon, altitudeFeet, secondsFromStart, note).npm run verify:media && npm test.It then appears on the globe.
Status matters. Many famous cases have ordinary explanations and are shown with the explanation first:
Unresolved means there isn't enough data, not "alien".
Paths are reconstructions from the cited reports and radar accounts, and each track states its basis. Average speeds are simply distance ÷ time between reported points.
Official releases are often region-only. The magenta ring is the whole area named in the release.
Blue Book pins mark the town in the file name, not the exact spot.
GEIPAN pins mark the commune named in the file. GEIPAN's classification is its own: a class D case is unexplained after investigation, not proven extraordinary.
NUFORC reports are unverified. They show where people report things.
MUFON and research-archive places are found automatically. A violet or teal pin is a town named in a journal report. That's usually where the sighting was, but sometimes it's a witness's hometown or where a report was filed. Every pin links to its page so you can check.
Night-side city lights are today's. When a case lights the globe for its moment, the lights on the night side are NASA's 2016 Black Marble, not the lights of the case year.
Times can be approximate. 54 older cases record only the date or part of the day. They are marked time approx., and the sky, weather and story say so.
.github/workflows/pages.yml tests and builds the site on every push to the default branch, then publishes it to a gh-pages branch that GitHub Pages serves.
gh-pages.gh-pages / (root).https://<user>.github.io/<repository>/.Any other static host works too. Run SITE_URL=https://your.site/ npm run build (SITE_URL goes into the link previews and the sitemap; add BASE_PATH=/subpath/ when it is not served from the root), then upload dist/. To try it in a container: docker run --rm -p 8080:80 -v "$PWD/dist:/usr/share/nginx/html:ro" nginx:alpine.
ci.yml runs the tests and a build on every push and pull request (codeql.yml scans the code, and Dependabot proposes dependency updates weekly). sync-official.yml re-syncs the official DVIDS releases every Monday (and the geomagnetic Kp series and the fireball record on the first Monday of the month), commits any change and redeploys the site. After each deploy, indexnow.yml sends the sitemap to Bing and the other IndexNow search engines and asks the Wayback Machine to keep a copy of the main pages. release.yml publishes a GitHub release from .github/release-notes/<tag>.md.
The build writes a page per case (case/<id>/), an index of them (case/), pages that group the cases by country, decade, status, kind of encounter, evidence and shape (browse/; a group needs two cases), the open data (open-data/), a sitemap.xml, and robots.txt, llms.txt and llms-full.txt (the cases as plain text for AI assistants; crawlers read these at the root of a host, so on a github.io/<repo>/ address they matter only on a custom domain). A case page opens the case on the globe at once only when its link ends in #globe, as links shared from the app do; reached any other way (a search result) it stays a readable page, so search engines index it. They use the address in SITE_URL, which pages.yml sets to https://<owner>.github.io/<repository>/. After changing cases, refresh their preview images with node scripts/build-cards.mjs against a running build, or run cards.yml from the Actions tab, which draws them on GitHub (with the satellite imagery) and commits them. For IndexNow, replace public/<key>.txt with your own key.
Corrections and new cases are welcome, especially with sources. CONTRIBUTING.md has the details, and AGENTS.md is the developer guide.
npm test first, and npm run verify:media if you touched case files. Interface text goes in all 15 languages (npm run i18n:add).src/i18n/locales/.Third-party data keeps its own licence; the MIT licence covers only the code.
33.3943, -104.5230, 33.39°N 104.52°W, 33°23'39"N 104°31'23"W, a military grid reference (13S ES 44360 95102), or a pasted Google Maps, OpenStreetMap, Apple Maps or geo: link. The HUD shows the MGRS grid under the camera, as fine as the height makes sense.?embed=1#/case/nimitz-tic-tac-2004 | The embeddable view: the globe and the case file only, with an Open full app link. Put it in an <iframe> |
?open=explain | Open a screen on load: explain (WHAT DID I SEE?), files, stats, space, log, about, tour or random. The installed app's shortcuts use these |
MUFON_UFO_Journal_-_Skylookmufon.json |
npm run build:geipan | GEIPAN's published case and testimony files (cnes-geipan.fr, CSV; the current export dates from February 2019). It joins them, restores the accents lost in the case file from the testimony file's vocabulary, geocodes each commune with the GeoNames France dump and converts observation times to UTC. | geipan.json |
npm run build:journals | Scans on the Internet Archive: the APRO Bulletin and MUFON chapter newsletters (Archives for the Unexplained), NICAP's U.F.O. Investigator (Serials in Microfilm) and CUFOS's International UFO Reporter. Same place finding and case matching as the MUFON build; undated newsletters are dated from their first pages and issue numbers. | journals.json |
npm run build:textindex | The OCR words of every MUFON and research-archive page (after the two builds above), split by first letter so a search downloads only what it needs. The text itself is not stored. | textindex/ |
npm run verify:media | Checks every Commons file, Wikipedia title, DVIDS id and Blue Book id that the case files reference | — |
npm run e2e | Playwright: the app in a real browser (desktop and phone), run in CI on every push. A weekly job also checks every cited link and opens an issue if one breaks. | — |
npm test | Vitest: case-file integrity (coordinates, taxonomy, track times, plausible altitudes), the region resolver, sky, weather, airspace and launch helpers, sighting-checker scoring, story text, OSM building tiles and dataset schemas | — |
scripts/build-skybox.py.