The components
Four standard Web Components — the browser's own, not a framework's. Each registers itself on import, each takes the same description of an observation as its input, and each composes the one before it.
Standard, and that is the whole design#
These are four Web Components — the browser's own standard for a custom element, not a component of anybody's framework. What follows from that is worth spelling out, because it is why the tool can be handed to you at all:
- They work in any page. A static site, WordPress, a React or Vue app, a
wiki, a hand-written HTML file. They are elements; a page that can hold a
<video>can hold these. - Nothing to build. No bundler, no compilation step, no configuration in your project. The module registers its element on import and the browser does the rest.
- Nothing to keep up with. There is no framework version to match, so they cannot be made obsolete by somebody else's major release.
- Their insides are their own. Each carries its markup and its styles in a shadow root, so your page's CSS cannot break them and they cannot break your page.
They compose in one line: <rr0-scene> holds an
<rr0-ufo>, and both <rr0-sighting> and
<rr0-sighting-editor> hold an <rr0-scene>. So everything
under <rr0-ufo> below is available in all four — through
.scene.ufoElement from the outermost, since the composition lives in a shadow
root.
What each one is for#
<rr0-ufo>— the phenomenon, and nothing else. The shape a witness drew, its colour and halo and movement, replayed on a bare background. It is the testimony without the world around it.<rr0-scene>— the world around it. The real sky, horizon, weather and ground of a stated date, hour and place, with the phenomenon composited over them. Useful on its own, for a sky with nothing in it at all.<rr0-sighting>— the testimony, to watch. A scene plus who is testifying, the observation's own metadata, its credits, and the lines that let a reader take it elsewhere. This is what a published sighting looks like.<rr0-sighting-editor>— the testimony, to reconstruct. Everything above plus the authoring toolbar: describe an observation, or correct one.
How they fit together#
You never write the nesting. Each element builds the one below it inside its own shadow root, so what your page contains is a single tag:
<rr0-sighting> who is testifying, the metadata panel, the embed lines
└─ <rr0-scene> the real sky, horizon, weather and decor
└─ <rr0-ufo> the canvas, the shape, playback
<rr0-sighting-editor> the eight authoring panels
└─ <rr0-scene> a scene, not a sighting: an editor has its own toolbar
└─ <rr0-ufo>
Which is why one script tag brings the ones underneath with it:
| Loading this | registers |
|---|---|
/lib/rr0-ufo.mjs | <rr0-ufo> |
/lib/rr0-scene.mjs | <rr0-scene>, <rr0-ufo> |
/lib/rr0-sighting.mjs | <rr0-sighting>, <rr0-scene>, <rr0-ufo> |
/lib/rr0-sighting-editor.mjs | <rr0-sighting-editor>, <rr0-scene>, <rr0-ufo> |
So a page showing a sighting and, further down, a bare sky of its own needs one script and two tags — the second element is already registered.
A composition can be reached into, one property at a time:
const sighting = document.querySelector("rr0-sighting")
sighting.scene // the <rr0-scene> it composes
sighting.scene.ufoElement // and the <rr0-ufo> under that
sighting.scene.ufoElement.play() // so playback is two properties away
<rr0-sighting-editor> keeps its own composition to itself: what it offers
a page is the recording — sightingData — and the event saying it changed.
Which one you want#
They are not variants of one bundle: each is self-contained, so load only the one you need. The three heavier ones carry Three.js and a star catalogue, which is what a real sky costs.
| What you are doing | Component | Module | gzip |
|---|---|---|---|
| Showing a UFO sighting — a case file, an article, a report | <rr0-sighting> | /lib/rr0-sighting.mjs | 249 KB |
| Letting somebody describe or correct one | <rr0-sighting-editor> | /lib/rr0-sighting-editor.mjs | 293 KB |
| Showing a sky with nothing in it — what a halo, a comet or a satellite pass looked like that night | <rr0-scene> | /lib/rr0-scene.mjs | 238 KB |
| Showing a sighting inside a scene of your own, with no toolbar over it | <rr0-scene> | /lib/rr0-scene.mjs | 238 KB |
| Illustrating a shape in the flow of an article, with no sky and no weight | <rr0-ufo> | /lib/rr0-ufo.mjs | 16 KB |
| Not sure | <rr0-sighting> | /lib/rr0-sighting.mjs | 249 KB |
Putting one on a page is two lines.
Detailed documentation#
What each takes, what it answers to, and what it draws — one page per component, because what you need from one of them is never what you need from the other three at the same moment.
<rr0-ufo>
The shape and its playback, with no sky behind it — the light one.
Read →
<rr0-scene>
The same, over the real sky and horizon of the recording's own date and place.
Read →
<rr0-sighting>
The standard view of a real account: one witness or several, with their toolbar.
Read →
<rr0-sighting-editor>
The whole authoring toolbar, for describing an observation or correcting one.
Read →
Putting one in your application#
After npm install @rr0/ufoathome:
import "@rr0/ufoathome/ufo" // registers <rr0-ufo>
import "@rr0/ufoathome/scene" // registers <rr0-scene>
import "@rr0/ufoathome/sighting" // registers <rr0-sighting>
import "@rr0/ufoathome/editor" // registers <rr0-sighting-editor>
Or copy the contents of the package's dist-embed* directories onto your own
server and point the <script src> there. Each module references its own
assets — the star catalogue, the weather audio — relative to itself, so it keeps
working from any path; just keep each bundle's files together. Nothing then depends on this
site at all.
Language#
Every label is translated by detection, with no picker: the page's own declared language
first — the nearest lang attribute, so <html lang="fr"> gets
French labels — then the browser's own preferences, then English. A page that declares nothing
falls through to the browser exactly as before.