Technical specification for the Nyx cosmic-observatory platform: astronomical type system, REST and WebSocket APIs, database schema, data pipelines, the library and application surface, and configuration. Every entity, enum, endpoint, and table below is traceable to source in
libs/nyx/*andapps/nyx/*.
This document is the authoritative technical reference for engineers working on or integrating with the Nyx domain. It covers the exact TypeScript types, REST endpoints, WebSocket message protocol, database schema, and environment configuration — the level of detail needed to implement a new feature, add a migration, or write client code against the API.
The sections follow a natural dependency order: the technology stack and algorithm standards first (since everything else builds on them), then the type system, then the API surface, then persistence, then the pipeline workers, and finally the full library and application inventories.
Technology Stack#
The table below lists the key technology choice at each architectural layer. Understanding this stack is essential before reading the sections that follow, since the API, schema, and validation patterns all flow directly from these choices.
| Layer | Technology |
|---|---|
| REST API framework | Hono + @hono/zod-openapi (OpenAPIHono), @hono/swagger-ui |
| HTTP runtime | @hono/node-server |
| Real-time | WebSocket (ws library), custom Nyx WS server + update scheduler |
| Database | PostgreSQL, accessed via pg; schema as Zod models in @nyx/database |
| Migrations | Knex migrations (@nyx/database migrations/) |
| Cache / rate limit | Redis (ioredis) for API rate-limit windows; in-process fallback |
| Pipeline runtime | Node.js workers (pino logging, prom-client metrics, undici) |
| Ephemeris kernel | astronomy-engine plus in-domain Meeus/VSOP-style implementations |
| Web clients | Vite + React + Three.js (@react-three/fiber, drei, xr) |
| Validation | Zod (catalog version) throughout |
| Testing | Vitest |
Note: the API uses raw
pg, not Drizzle.@nyx/databasedefines schema as Zod object schemas and ships Knex migration files; there is no Drizzle ORM layer.
Astronomical Algorithm Standards#
The computation libraries in Nyx implement classical positional-astronomy algorithms throughout, rather than delegating all calculation to an external dependency. This is a deliberate choice: it makes the algorithms independently testable against known-correct reference values and keeps the domain's accuracy guarantees under its own control.
Ephemeris, coordinate, and event code implements Meeus-style analytic series,
Besselian-element eclipse prediction, SGP4 TLE propagation, and Kepler-equation
solvers. The domain additionally depends on the astronomy-engine package for
high-precision solar-system positions where the Meeus approximations reach their
accuracy limits. Coordinate types carry their reference frame and epoch
explicitly so equatorial, horizontal, galactic, and ecliptic frames cannot be
silently mixed.
Core Type System (@nyx/types)#
@nyx/types is the shared TypeScript type library that every other @nyx/*
package imports from. It exports six modules — coordinates, celestial,
time, observer, orbital, visualization — re-exported from
src/index.ts. All types below are exact as they appear in source.
Coordinate Types (coordinates.ts)#
The coordinate types encode all the information needed to identify a location in the sky unambiguously — including the reference frame and epoch, which are frequently omitted by naive implementations and lead to subtle cross-library bugs.
Angular unit aliases (all number): Degrees, Radians, Arcminutes,
Arcseconds, Hours, Milliarcseconds.
Sexagesimal representations encode angles in base-60 notation as astronomers traditionally record them:
SexagesimalAngle—degrees,minutes,seconds,sign(1 | -1)HMSAngle—hours,minutes,secondsDMSAngle—degrees,arcminutes,arcseconds,sign(1 | -1)
CoordinateFrame union:
ICRS | J2000 | B1950 | GALACTIC | ECLIPTIC | HORIZONTAL | SUPERGALACTIC.
Epoch union: 'J2000.0' | 'B1950.0' | 'J2050.0' | number.
Coordinate interfaces:
EquatorialCoordinates—ra(Degrees, 0–360),dec(Degrees, −90..+90), optionalframe, optionalepochAstrometricCoordinatesextendsEquatorialCoordinates— addspmRA,pmDec(mas/yr),parallax(mas),radialVelocity(km/s),observationEpoch(Julian year)HorizontalCoordinates—altitude,azimuth(Degrees)ApparentHorizontalCoordinatesextends it —trueAltitude,refraction(Arcminutes),airMassGalacticCoordinates—l,b;SupergalacticCoordinates—sgl,sgbEclipticCoordinates—lambda,beta, optionalepochCartesianPosition—x,y,z,unit: DistanceUnitCartesianVelocity—vx,vy,vz,unit: VelocityUnitStateVector—position,velocity,frame,epoch
Unit unions: DistanceUnit = km | AU | pc | kpc | Mpc | ly | m;
VelocityUnit = km/s | AU/day | m/s | c.
Derived geometry: AngularSeparation (degrees/arcminutes/arcseconds),
PositionAngle (degrees + from/to), FieldOfView (rectangular),
CircularFieldOfView, GreatCircleArc, SphericalTriangle.
Transformation records: CoordinateTransformResult<T> and
CoordinateCorrection whose type is one of
precession | nutation | aberration | parallax | proper_motion | refraction | light_time.
Celestial Object Types (celestial.ts)#
The celestial object types form a discriminated union that covers every class of
object in the domain's catalogs. Code that works generically on any catalog
query result uses CelestialObject; code that knows it is handling, say, an
exoplanet uses Exoplanet directly.
CelestialObjectType union (18 values): star, double_star,
variable_star, planet, dwarf_planet, moon, asteroid, comet,
galaxy, nebula, cluster, quasar, pulsar, black_hole,
supernova_remnant, satellite, meteor_shower, unknown.
CelestialObjectBase — id, type, coordinates
(EquatorialCoordinates), catalogs (CatalogIdentifiers), optional
magnitudes, optional updatedAt.
Magnitudes — optional photometric bands: apparent, absolute, B, V,
R, I, J, H, K, U, G.
ColorIndices — BV, UB, VR, VI, JH, HK, BPRP.
CatalogIdentifiers — cross-reference IDs: hip, tyc, gaia, hd,
hr, sao, flamsteed, bayer, name, variable, ngc, ic, messier,
simbad, twoMass.
Stars — SpectralClassification (class is one of
O B A F G K M L T Y W C S; optional subclass, luminosityClass of
Ia Ib II III IV V VI VII, peculiarities); StellarProperties
(temperature, luminosity, mass, radius, surfaceGravity, metallicity,
age, rotationPeriod); Star extends CelestialObjectBase with
astrometry, spectralType, properties, colorIndices, distance,
constellation.
Double stars — DoubleStar (primary: Star, companions: StarCompanion[],
separation, positionAngle, orbitalPeriod, isPhysical); StarCompanion
(designation, magnitude, spectralType, separation, positionAngle).
Variable stars — VariableStarType =
ECLIPSING | PULSATING | ERUPTIVE | ROTATING | X-RAY | OTHER;
VariableStarClass =
EA EB EW CEP DCEP RR DSCT MIRA SR NOVA SN FLARE GCAS MISC; VariableStar with
variableType, variableClass, maxMagnitude, minMagnitude, period,
epochMax, spectralType, gcvsName.
Solar-system bodies — SolarSystemBodyType =
planet | dwarf_planet | moon | asteroid | comet; SolarSystemBodyProperties
(mass, radius, density, surfaceGravity, escapeVelocity,
rotationPeriod, axialTilt, albedo, surfaceTemperature, atmosphere);
AtmosphericComposition (compound/percentage); Planet, Moon, Asteroid
(taxonomicClass, isPHA, orbitFamily), Comet (cometType =
periodic | non_periodic | great | sungrazer), DiscoveryInfo.
Exoplanets — ExoplanetDetectionMethod =
transit | radial_velocity | direct_imaging | microlensing | astrometry | timing | disk_kinematics;
Exoplanet (typed as type: 'planet') with hostStar, detectionMethod,
mass, massIsMinimum, radius, orbitalPeriod, semiMajorAxis,
eccentricity, equilibriumTemp, inHabitableZone, distance.
Deep-sky objects — DeepSkyObjectType =
galaxy | nebula | cluster | quasar | pulsar | black_hole | supernova_remnant;
GalaxyMorphology (Hubble sequence: E0–E7, S0, Sa–Sd, SBa–SBd, Irr,
cD, BCD, dE, dSph); Galaxy, NebulaType
(emission | reflection | dark | planetary | supernova_remnant | protoplanetary),
Nebula, ClusterType (open | globular | association | moving_group),
StarCluster.
Search — CelestialSearchParams (types, magnitude limits, cone-search
center/radius, catalogId, namePattern, constellation, limit,
offset); CelestialSearchResult<T> (objects, totalCount, queryTimeMs).
The discriminated union CelestialObject covers Star, DoubleStar,
VariableStar, Planet, Moon, Asteroid, Comet, Exoplanet, Galaxy,
Nebula, StarCluster.
Time Types (time.ts)#
These types cover every time representation used in astronomical computation. Astronomical code uses multiple incompatible time scales, and making them distinct types prevents mixing them accidentally.
Exports JulianDate, ModifiedJulianDate, JulianDayNumber, JulianDateSpec,
TimeScale, TimeScaleConversion, sidereal-time types (SiderealHours,
SiderealDegrees, GreenwichSiderealTime, LocalSiderealTime), epochs
(StandardEpoch, BesselianYear, JulianYear, EpochSpec), calendar types
(GregorianDate, JulianCalendarDate, DateRange), DeltaT/DeltaTSource,
LeapSecond, TimeInterval/TimeUnit, TimeConstants, phenomena types
(RiseTransitSetTimes, TwilightTimes, MoonPhase, LunarPhaseInfo),
TimeZoneInfo, and formatting types.
Observer Types (observer.ts)#
Observer types describe the physical context of a human observing session — location, equipment, atmospheric conditions, and the session record itself.
Exports GeographicCoordinates, ObserverLocation, Observer,
AtmosphericConditions, ObserverEquipment, horizon types (HorizonProfile,
HorizonPoint, HorizonCheckResult), site types (ObservingSite,
TelescopeInfo, TelescopeType, MountType), visibility types
(VisibilityAssessment, VisibilityFactor, SeasonalVisibility), weather
types (ObservingForecast, HourlyForecast, SkyBrightness), and session
types (ObservationSession, SessionTarget).
Orbital Types (orbital.ts)#
Orbital types represent everything needed to describe and propagate an orbit: element sets, state vectors, perturbation models, and the events that occur at specific orbital configurations.
KeplerianElements—a,e,i,node(Ω),peri(ω),M,epoch, optionalframe(ecliptic | equatorial)ExtendedOrbitalElements— addslongPeri,meanLong,q,Q,period,n,trueAnomaly,eccentricAnomaly,TTwoLineElement/TLELine1/TLELine2— full parsed TLE structure (classification=U | C | S, BSTAR drag, mean motion, RAAN, etc.)EphemerisPoint,EphemerisTable,EphemerisRequest—stepUnitisdays | hours | minutes;frameisheliocentric | geocentric | topocentric;aberrationisnone | apparent | astrometricPerturbation/PerturbationType(gravitational | oblateness | solar_radiation | atmospheric_drag | relativistic | tidal);ElementType=osculating | meanOrbitalEventType=perihelion | aphelion | ascending_node | descending_node | opposition | conjunction | greatest_elongation | quadrature | stationary_point | eclipse | transit | occultation;OrbitalEvent,Conjunction,OppositionEclipseType=total_solar | partial_solar | annular_solar | hybrid_solar | total_lunar | partial_lunar | penumbral_lunar;Eclipse(Besselian-style fields: contacts C1–C4,gamma,sarosNumber,pathCoordinates)PlanetaryTransit,ExoplanetTransit,SatellitePass,SatelliteFlareOrbitDeterminationInput,OrbitDeterminationResult(orbitType=elliptic | parabolic | hyperbolic)
Visualization Types (visualization.ts)#
Visualization types describe everything needed to configure and render a sky chart — from the projection algorithm to individual renderable objects and their display symbols.
Exports projection/grid types (Projection, GridType), chart configuration
(SkyChartConfig, SkyChartDisplayOptions, SkyChartColors), renderable
objects (RenderableObject, RenderableStar, RenderableDeepSkyObject,
DSOSymbol, RenderablePlanet), constellation render types
(RenderableConstellation, ConstellationLine, ConstellationBoundary),
interactivity types, animation types, 3D-scene types (Scene3DConfig,
Camera3D, Lighting3D, Background3D, Scale3D), export types, and
accessibility types.
REST API (apps/nyx/api)#
The API is an OpenAPIHono application. apps/nyx/api/src/index.ts boots an
HTTP server (@hono/node-server) and attaches the WebSocket server on the same
port. The static OpenAPI document is loaded from
libs/openapi/docs/nyx/openapi.yaml (validated as OpenAPI 3.1.0, title
Nyx Astronomy API).
Middleware Chain#
The middleware chain is defined in app.ts and runs in this fixed order for
every request. Understanding the order matters when adding new middleware,
because earlier middleware can short-circuit later ones.
Applied in order: secureHeaders → cors (methods GET, OPTIONS) → logger
→ timing → prettyJSON → requestId → onError(errorHandler). On /api/*
two further middlewares run after the above: apiKeyAuth then rateLimit.
Authentication#
API keys are passed via the X-API-Key header (the middleware also accepts
Authorization: Bearer <key> and an optional query parameter). Anonymous access
is allowed by default — a missing key yields tier anonymous. Keys must match
^nyx_(free|pro|enterprise)_[a-zA-Z0-9]{6,32}$.
There are two validator implementations, used in different environments:
- Default validator: an in-memory map of three demo keys
(
nyx_free_demo123456,nyx_pro_testkey789,nyx_enterprise_corp456) plus any keys supplied viaNYX_LOCAL_API_KEYS. This is the validator that runs when no database URL is configured. - Production validator:
createPgApiKeyValidator(databaseUrl)performs a SHA-256-hashed lookup against theapi_keystable, supporting revocation, expiry, and feature scoping. - Tier feature sets: free →
basic, search, ephemeris; pro → addsevents, satellites, batch; enterprise → addswebhook, priority. - Helpers:
getApiKeyInfo,hasFeature,requireTier.
Rate Limiting#
Rate limits are enforced by a tiered fixed-window limiter (rate-limit.ts).
Redis is used when NYX_REDIS_URL or REDIS_URL is set; otherwise an
in-process store is used. The limits below are requests per minute with a burst
allowance:
RATE_LIMIT_TIERS (requests per minute / burst): anonymous 60/10, free
300/30, pro 1000/100, enterprise 5000/500. Responses expose
X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset headers.
Error Format#
All API errors follow RFC 7807 Problem Details (application/problem+json).
ProblemDetailSchema fields: type (URI), title, status, optional
detail, instance, requestId, timestamp, code. ValidationErrorSchema
extends it with a per-field errors array.
Endpoint Surface#
All routes are mounted under /api/v1. Success responses use the envelope
{ success: true, data, [pagination], meta: { requestId, timestamp } }.
Service-info and health (unauthenticated):
| Method | Path | Description |
|---|---|---|
| GET | / |
Service metadata + endpoint index |
| GET | /health |
Health check (status, uptime) |
| GET | /api/v1 |
API version + endpoint list |
| GET | /api/v1/openapi.json |
Static OpenAPI document |
| GET | /api/docs |
Swagger UI |
Objects (routes/objects.ts) — catalog queries for celestial objects:
| Method | Path | Description |
|---|---|---|
| GET | /api/v1/objects |
Paginated celestial-object list with filters |
| GET | /api/v1/objects/search |
Relevance-scored search by name/designation |
| GET | /api/v1/objects/{id} |
Single object by ID or catalog designation |
/objects query params (ObjectQueryParamsSchema + PaginationParamsSchema):
type (ObjectTypeSchema), catalog (CatalogSchema), constellation,
minMagnitude, maxMagnitude, page, limit (max 100). /objects/search
params: q (required), type, limit. Search results carry score (0–1) and
matchedField.
Ephemeris (routes/ephemeris.ts) — position and visibility calculations for
celestial objects at a given time and location:
| Method | Path | Description |
|---|---|---|
| GET | /api/v1/ephemeris |
Position/visibility over a time range |
| GET | /api/v1/ephemeris/position |
Current position of an object |
| GET | /api/v1/ephemeris/rise-set |
Rise / transit / set times for a date |
/ephemeris query (EphemerisRequestSchema): objectId, startTime,
endTime, step (default 1h), latitude, longitude, elevation. The
response (EphemerisResponseSchema) contains entries[]
(EphemerisEntrySchema: timestamp, jd, equatorial, optional horizontal,
ecliptic, distance {au, km, lightTime}, magnitude, phase
{illumination, angle}, angularSize, elongation, constellation,
isVisible, riseTime, transitTime, setTime) and a summary block.
Events (routes/events.ts) — upcoming and past celestial events such as
eclipses, conjunctions, and meteor showers:
| Method | Path | Description |
|---|---|---|
| GET | /api/v1/events |
Events in a date range with filters |
| GET | /api/v1/events/upcoming |
Events in the next 7 days |
| GET | /api/v1/events/types |
Catalog of event types with categories |
| GET | /api/v1/events/{id} |
Single event by ID |
/events query (EventQueryParamsSchema + pagination): startDate, endDate,
type (comma-separated), types (deprecated alias), importance, latitude,
longitude. Event categories returned by /events/types: lunar, solar,
planetary, meteor, eclipse, seasonal.
Satellites (routes/satellites.ts) — real-time satellite positions and pass
predictions:
| Method | Path | Description |
|---|---|---|
| GET | /api/v1/satellites |
Paginated satellite list |
| GET | /api/v1/satellites/categories |
Satellite category catalog |
| GET | /api/v1/satellites/passes |
Pass predictions for a location |
| GET | /api/v1/satellites/{id} |
Single satellite by NORAD ID |
| GET | /api/v1/satellites/{id}/passes |
Pass predictions for one satellite |
/satellites query (SatelliteQueryParamsSchema): category
(SatelliteCategorySchema), status (SatelliteStatusSchema), search,
minAltitude, maxAltitude. /satellites/passes query
(SatellitePassQueryParamsSchema): satelliteId (default ISS), latitude,
longitude (required), elevation, days (max 14), minElevation,
visibleOnly.
API Schema Enums#
These enums are used across the request validation schemas and appear in the OpenAPI document. They are the complete, canonical lists as of the current source.
ObjectTypeSchema:star, planet, moon, asteroid, comet, galaxy, nebula, cluster, constellation, satellite, otherCatalogSchema:messier, ngc, ic, hipparcos, tycho, gaia, sao, hd, yale, gcvs, mpc, jpl, norad, otherEventTypeSchema(33 values):solar_eclipse, lunar_eclipse, planetary_conjunction, planetary_opposition, planetary_transit, greatest_elongation, meteor_shower, comet_perihelion, asteroid_close_approach, new_moon, first_quarter, full_moon, last_quarter, supermoon, lunar_occultation, solstice, equinox, perihelion, aphelion, iss_pass, satellite_flare, satellite_decay, variable_star_maximum, variable_star_minimum, nova, supernova, conjunction, opposition, occultation, transit, rise, set, meridian_transit, otherEventVisibilitySchema:global, regional, local, not_visibleEventImportanceSchema:major, moderate, minorSatelliteCategorySchema:space_station, starlink, weather, communication, navigation, earth_observation, scientific, military, amateur, debris, otherSatelliteStatusSchema:active, inactive, decayed, unknown
API Data Sources#
The API services back their responses with bundled-catalog libraries and sample
data rather than a live database read path. This is important to understand when
debugging: a query against /api/v1/objects does not hit PostgreSQL; it filters
an in-memory array.
objects-servicebuilds its catalog fromALL_MESSIER_OBJECTS(@nyx/messier) mapped into the APICelestialObjectshape; queries filter that in-memory array.events-serviceserves a fixed in-module list of sample events (ASTRONOMICAL_EVENTS, ~11 entries for 2024).satellites-serviceusescreateSatelliteTrackerandparseTLEfrom@nyx/realtime-satelliteswith vendored TLE data for pass prediction.ephemeris-serviceorchestrates@nyx/ephemerisand@nyx/constellations.
The celestial_events table and createPgApiKeyValidator exist for production
deployments; the default request path is catalog/sample-data backed.
WebSocket API (apps/nyx/api/src/websocket)#
The WebSocket API provides real-time pushes for position updates, satellite passes, and visibility alerts. It uses a custom server rather than a generic pub/sub layer so that the subscription model (with per-tier budgets) and the update scheduling logic can be kept fully under the domain's control.
A custom WebSocket server (NyxWSServer, created by createNyxWSServer) is
attached to the HTTP server at path /ws (configurable via WS_PATH). The
setupNyxWebSocket helper wires the server, registers position/satellite/alert
handlers, and starts an UpdateScheduler. Ping interval 30 s, ping timeout 10
s.
Message Types (NyxMessageType)#
The complete set of message types, grouped by purpose:
- System:
ping,pong,error,auth,auth_response - Subscription:
subscribe,unsubscribe,subscribed,unsubscribed - Position:
position:update,position:batch - Satellite:
satellite:position,satellite:pass:start,satellite:pass:update,satellite:pass:end,satellite:batch - Alerts:
alert:event,alert:pass,alert:visibility,alert:iss - Time:
time:sync,time:tick
Channels (NyxChannel)#
Channels determine what data a client is subscribed to. The {id} and {type}
patterns allow narrowing to a specific object or event type.
objects:*, objects:{id}, satellites:*, satellites:{id}, events:*,
events:{type}, passes:*, passes:{observer}, time:sync.
Message Envelope#
All messages use the NyxMessage<T> envelope: type, optional payload,
channel, id, timestamp. Subscription messages carry options
{ updateInterval, precision: 'low'|'medium'|'high', observer }.
Push Payloads#
The payload type for each push message:
PositionUpdate/PositionBatch— object positions withequatorial, optionalhorizontal,distance,magnitude,phase,isVisibleSatellitePosition/SatelliteBatch— geodetic lat/lon/altitude, velocity, footprint, optional observer-relativehorizontal/rangeSatellitePassEvent—phase(start | rising | culmination | setting | end), azimuth/elevation/range,progressEventAlert,PassAlert,VisibilityAlert—AlertSeverityisinfo | notice | warning | urgentTimeSyncPayload,TimeTickPayload— server time, Julian date, sidereal time
Tier Limits (DEFAULT_TIER_LIMITS)#
Per-tier TierLimits control how many concurrent connections and subscriptions
a client may hold, how frequently updates are sent, and how many messages per
minute the server will push. Higher tiers get higher frequencies — enterprise
gets 10 ms minimum intervals compared to 5000 ms for anonymous.
| Tier | Connections | Subscriptions | Min interval | Msgs/min |
|---|---|---|---|---|
| anonymous | 1 | 5 | 5000 ms | 60 |
| free | 3 | 20 | 1000 ms | 300 |
| pro | 10 | 100 | 100 ms | 1000 |
| enterprise | 100 | 1000 | 10 ms | 10000 |
The WS API-key validator in index.ts maps key prefixes to tiers (nyx_pro_ →
pro, nyx_ent_ → enterprise, other nyx_ → free).
Database Schema (@nyx/database)#
@nyx/database exports Zod schema models (src/schema/) and Knex migration
files (src/migrations/, exported as the migrations namespace). PostgreSQL
extensions and enum types are created in the first migration.
Migration Tables#
The 9 migrations (20260118000001–20260118000009) create the ~36 tables
below. They are grouped here by the domain concern each group addresses.
- Celestial objects:
celestial_objects,stars,solar_system_objects,exoplanets,galaxies,nebulae,star_clusters - Orbital mechanics:
orbital_elements,tle_elements,ephemeris_entries,rise_transit_set_times,eclipse_data,celestial_events,lunar_phases,meteor_showers,perturbation_records - Catalog cross-reference:
catalog_metadata,catalog_cross_references,name_aliases,constellations,constellation_boundaries,constellation_star_patterns,artificial_satellites - User data:
observation_logs,saved_views,custom_annotations,tour_definitions,tour_stops,tour_progress,observing_lists,observing_list_items,user_preferences,achievement_definitions,user_achievements,user_statistics - API:
api_keys
Migration 6 creates indexes; migration 7 seeds initial data; migration 8 adds a
uniqueness index used by the event-calculator pipeline; migration 9 creates
api_keys (PK key_hash, tier check constraint of free/pro/enterprise,
feature text[], expiry/revocation columns).
Schema Models — Celestial Objects (schema/celestial-objects.ts)#
These Zod schemas are the authoritative definitions for each object type stored
in the database. Each model has a Create…InputSchema variant that omits id
and timestamp fields.
Common Zod schemas: EquatorialCoordinatesSchema (ra 0–360, dec −90..+90,
epoch default 2000.0, frame of ICRS|FK5|FK4|galactic|ecliptic),
ProperMotionSchema, ParallaxSchema, RadialVelocitySchema,
MagnitudeSchema (bands V B U R I G BP RP J H K), CatalogIdentifiersSchema
(20+ catalog IDs), NameAliasesSchema.
Object models — each with a Create…InputSchema (omits id/timestamps):
StarSchema—StarTypeSchema(main_sequence, giant, supergiant, hypergiant, subgiant, subdwarf, white_dwarf, neutron_star, brown_dwarf, red_dwarf, blue_dwarf, carbon_star, wolf_rayet, pulsar, magnetar, black_hole, unknown),SpectralClassificationSchema,StellarPropertiesSchema,VariableStarDataSchema(VariableTypeSchema— 22 classes), andMultipleStarDataSchemaExoplanetSchema—PlanetTypeSchema(terrestrial, super_earth, mini_neptune, neptune_like, gas_giant, hot_jupiter, hot_neptune, ice_giant, ocean_world, lava_world, dwarf_planet, unknown),DetectionMethodSchema(10 methods),PlanetaryOrbitSchema,PlanetaryPropertiesSchema,HabitabilityMetricsSchema(inHabitableZone,esi,phi,potentialWater,insolation)SolarSystemPlanetSchema— physical and orbital properties, moon count, rings, atmosphere/surface composition recordsGalaxySchema—GalaxyMorphologySchema(Hubble sequence incl.LIRG,ULIRG),GalaxyActivitySchema(normal, seyfert1, seyfert2, liner, quasar, blazar, radio_galaxy, starburst, agn, ulirg, unknown),GalaxyPropertiesSchemaNebulaSchema—NebulaTypeSchema(15 values incl.hii_region,bok_globule,herbig_haro),NebulaPropertiesSchemaStarClusterSchema—ClusterTypeSchema(open_cluster, globular_cluster, stellar_association, asterism, moving_group, embedded_cluster, unknown),TrumplerClassSchema,ClusterPropertiesSchemaDeepSkyObjectSchema— generic unified-query model withDeepSkyObjectTypeSchema(15 values)
Search schemas: CoordinateSearchBoxSchema, ConeSearchSchema,
MagnitudeFilterSchema, PaginationSchema (limit max 1000),
SortOrderSchema.
Schema Models — Catalogs (schema/catalogs.ts)#
Catalog schemas handle identifier cross-referencing — the logic of knowing that HD 19445, HIP 14544, and Gaia DR3 2534784854721380352 all refer to the same object.
CatalogTypeSchema— ~55 catalog identifiers across star, variable-star, double-star, deep-sky, planetary, satellite, and database categories (hipparcos,gaia_dr3,messier,ngc,ic,mpc,simbad,ned,norad, …)CatalogObjectTypeSchema— 31 object classificationsDataQualitySchema—excellent, good, fair, poor, suspect, unknownCatalogMetadataSchema,CatalogIdentifierSchema,CatalogCrossReferenceSchema,NameAliasSchema(NameTypeSchema— 16 name types includingarabic,chinese,indigenous),ConstellationInfoSchemaConstellationAbbreviationSchema— all 88 three-letter IAU abbreviations- Query schemas:
CatalogSearchQuerySchema,NameSearchQuerySchema,CrossReferenceQuerySchema,CrossReferenceResultSchema
Schema Models — Orbital Mechanics (schema/orbital-mechanics.ts)#
OrbitalBodyTypeSchema (15 values incl. centaur, tno, kuiper_belt,
oort_cloud), OrbitalReferenceFrameSchema (heliocentric_j2000, teme,
gcrf, …), KeplerianElementsSchema with full element set and per-element
uncertainties.
Schema Models — User Data (schema/user-data.ts)#
User data schemas cover the full observing session lifecycle: site conditions when the session was conducted, equipment used, per-object observation notes, saved views and annotations, educational tour progress, and achievement records.
- Observation logs —
SeeingConditionsSchema,TransparencySchema,BortleScaleSchema(1–9),WeatherConditionsSchema,EquipmentTypeSchema(11 types),EquipmentUsedSchema,ObservationTypeSchema(15 types),ObservationLogSchema - Saved views —
ViewTypeSchema,ProjectionTypeSchema(8 projections incl.mollweide,aitoff,hammer,gnomonic),ViewConfigurationSchema,SavedViewSchema - Annotations —
AnnotationTypeSchema(9 types),AnnotationPointSchema,AnnotationStyleSchema,CustomAnnotationSchema - Educational tours —
TourDifficultySchema(beginner, intermediate, advanced, expert),TourCategorySchema(15 categories),TourStepTypeSchema(9 step types),StepStatusSchema,TourStepDefinitionSchema,TourDefinitionSchema,TourProgressSchema - Achievements —
AchievementTypeSchema(13 types),AchievementDefinitionSchema(raritycommon…legendary),UserAchievementSchema - User preferences —
UserPreferencesSchema(default location, units, notification flags, theme incl.night_vision) - Observing lists —
ObservingListItemSchema,ObservingListSchema
Data Pipelines (apps/nyx/pipelines)#
The pipelines application contains four independent Node.js worker entry points. Each pipeline runs on its own schedule and writes results to PostgreSQL for the API to serve. They are intentionally kept separate so that a slow catalog sync does not block satellite pass predictions, and a failing ephemeris generation does not affect event calculations.
The four pipelines, registered in PIPELINES (src/index.ts):
| Pipeline | Entry point | Purpose |
|---|---|---|
tle-updater |
tle-updater.ts |
Fetch TLE data, refresh satellite orbital state |
catalog-syncer |
catalog-syncer.ts |
Sync Gaia/Hipparcos catalog data into object tables |
ephemeris-generator |
ephemeris-generator.ts |
Pre-compute solar-system positions |
event-calculator |
event-calculator.ts |
Predict conjunctions/eclipses and persist to celestial_events |
The event-calculator works by walking pairs of visible bodies with the
@nyx/events conjunction scanner and Bessel-element eclipse predictors, then
upserting results into the celestial_events table via pg
(INSERT INTO celestial_events …). Each pipeline can run directly or as a
Kubernetes CronJob. Shared common/ modules provide a pino logger, a
prom-client metrics registry, and an HTTP health server gated by
METRICS_ENABLED. Pipeline dependencies include @nyx/gaia, @nyx/hipparcos,
@nyx/coordinates, @nyx/database, @nyx/ephemeris, @nyx/events,
@nyx/orbital, @nyx/realtime-satellites, @nyx/time, and astronomy-engine.
Library Surface (libs/nyx/*)#
The Nyx domain ships 75 published packages organised into nested groups. Package names below are the canonical npm-style identifiers.
Core / Foundation#
| Package | Path | Purpose |
|---|---|---|
@nyx/types |
libs/nyx/types |
Shared TypeScript type system (six modules) |
@nyx/constants |
libs/nyx/constants |
Physical and astronomical constants |
@nyx/coordinates |
libs/nyx/coordinates |
Coordinate-system transforms |
@nyx/time |
libs/nyx/time |
Time scales, Julian date, sidereal time, Delta-T |
@nyx/utils |
libs/nyx/utils |
Angular and magnitude math helpers |
@nyx/database |
libs/nyx/database |
Zod schema models + Knex migrations |
Astronomical Computation#
| Package | Path | Purpose |
|---|---|---|
@nyx/ephemeris |
libs/nyx/ephemeris |
Solar-system position computation |
@nyx/orbital |
libs/nyx/orbital |
Kepler/n-body, perturbations, Lagrange points, propagation |
@nyx/positional |
libs/nyx/positional |
Topocentric correction, refraction, rise/set |
@nyx/events |
libs/nyx/events |
Eclipse / conjunction / occultation / transit / meteor / aurora / satellite-pass / supermoon / deep-sky event prediction, plus calendar sync (largest computation library) |
@nyx/constellations |
libs/nyx/constellations |
Multi-cultural constellation database + artwork |
@nyx/mythology |
libs/nyx/mythology |
Constellation mythology data |
@nyx/time-travel |
libs/nyx/time-travel |
Historical/future sky reconstruction |
@nyx/sky-clock |
libs/nyx/sky-clock |
Sky-event materialiser, observer-location bucketing |
Catalogs — Star Catalogs (libs/nyx/catalogs)#
@nyx/hipparcos, @nyx/gaia, @nyx/tycho, @nyx/bright-stars, @nyx/simbad,
@nyx/star-query (multi-catalog unified query).
Catalogs — Deep Sky (libs/nyx/catalogs/deep-sky)#
@nyx/messier, @nyx/ngc-ic, @nyx/nebulae, @nyx/clusters, @nyx/snr,
@nyx/pulsars, @nyx/neutron-stars, @nyx/black-holes, @nyx/quasars,
@nyx/gravitational-waves. Plus @nyx/supernovae, @nyx/ned, @nyx/sdss.
Catalogs — Exoplanets and Solar System#
Exoplanets: @nyx/nasa-exoplanets, @nyx/open-exoplanets. Solar system
(libs/nyx/catalogs/solar-system): @nyx/planets, @nyx/moons,
@nyx/horizons, @nyx/mpc, @nyx/neo, @nyx/comets. Plus @nyx/spacecraft.
Analysis (libs/nyx/analysis)#
@nyx/galaxy-classification, @nyx/habitability (habitable zone, Earth
Similarity Index, atmospheric retention, tidal locking), @nyx/visualization
(chart generation).
Real-Time (libs/nyx/realtime)#
@nyx/realtime-satellites (TLE parsing + SGP4 satellite tracker),
@nyx/realtime-solar, @nyx/realtime-neo, @nyx/realtime-events.
Renderer (libs/nyx/renderer)#
12 WebGL/Three.js rendering packages: @nyx/renderer-core,
@nyx/renderer-background, @nyx/renderer-stars (published as
@nyx/star-colors), @nyx/renderer-planets, @nyx/renderer-galaxies,
@nyx/renderer-nebulae, @nyx/renderer-clusters, @nyx/renderer-exotic,
@nyx/renderer-hdr, @nyx/renderer-lod, @nyx/renderer-scale,
@nyx/renderer-post-processing.
Widgets, Audio, Education, Integrations, Visualization#
- Widgets (
libs/nyx/widgets):@nyx/widget-iss-tracker,@nyx/widget-moon-phase,@nyx/widget-star-map - Audio (
libs/nyx/audio):@nyx/audio-sonification,@nyx/audio-ambient - Education (
libs/nyx/education):@nyx/lesson-framework,@nyx/quiz-system - Integrations (
libs/nyx/integrations):@nyx/telescope,@nyx/stellarium,@nyx/planetarium - Visualization (
libs/nyx/visualization):@nyx/galaxy-distribution
Clients and Cross-Domain#
| Package | Path | Purpose |
|---|---|---|
@nyx/client |
libs/nyx/client |
Hand-written typed HTTP client for the API |
@nyx/api-client |
libs/nyx/api-client |
Client with OpenAPI-generated types |
@nyx/lilith-integration |
libs/nyx/lilith-integration |
Cosmic-meditation content bridge to Lilith |
libs/nyx/client-python exists as a Python client package (pyproject.toml, no
TypeScript sources). libs/nyx/docs contains design documents
(architecture.md, caching-strategy.md) — it is not a published package.
@nyx/lilith-integration — Cosmic Meditation Bridge#
@nyx/lilith-integration does not handle Lilith domain events. It is a
content/state library: it provides curated meditation material derived from
cosmic imagery, which Lilith can consume without needing to understand
astronomical algorithms. Nothing in this package computes positions or queries
catalogs.
CosmicMeditationTheme(8),SessionIntensity(gentle | moderate | deep | transcendent),AwarenessPhase(6 phases),CosmicBreathPattern(5)- Content collections:
COSMIC_VISUALIZATIONS(8 visualizations),SPACE_PARALLELS(8 inner/outer-space parallels),CONSCIOUSNESS_EXERCISES(6 exercises),BREATH_PATTERNS LilithBridgeManager— session lifecycle, breath-phase animation, exercise navigation; emitsLilithBridgeEventTypeevents (session_started,phase_changed,breath_cycle_completed, …)- Zod schemas:
SessionStateSchema,UserPreferencesSchema,SessionConfigSchema
Application Surface (apps/nyx/*)#
The Nyx domain ships 22 packaged applications. Six are top-level apps; the
education directory holds 12 packaged apps and the tools directory holds 4.
Top-Level Applications#
| Application | Package | Path | Stack |
|---|---|---|---|
| API | @nyx/api |
apps/nyx/api |
Hono + OpenAPI + ws |
| Star Map | @nyx/star-map |
apps/nyx/star-map |
Vite + React + Three.js |
| VR Planetarium | @nyx/vr-planetarium |
apps/nyx/vr-planetarium |
React-Three-Fiber + WebXR |
| AR Sky | @nyx/ar-sky |
apps/nyx/ar-sky |
React-Three-Fiber + WebXR |
| Mobile | @nyx/mobile |
apps/nyx/mobile |
React + idb-keyval |
| Pipelines | @nyx/pipelines |
apps/nyx/pipelines |
Node.js workers |
star-map is the largest application (~189 source files) and contains feature
modules for navigation, planning, collections, constellations, spacecraft,
satellites, mythology, time-travel, filters, tonight-view, journal, audio,
meditation, solar, NEO, and bookmarks. ar-sky and vr-planetarium depend on
@nyx/realtime-solar and the React-Three ecosystem.
Education Applications (apps/nyx/education)#
- Courses:
@nyx/fundamentals-course,@nyx/solar-system-course,@nyx/stellar-course,@nyx/galactic-course,@nyx/cosmology-course - Challenges:
@nyx/star-identification,@nyx/orbital-mechanics - Demos:
@nyx/hr-diagram,@nyx/spectroscopy,@nyx/distance-ladder,@nyx/light-speed,@nyx/gravity-well
Tools Applications (apps/nyx/tools)#
@nyx/astrophotography, @nyx/light-curves, @nyx/observation-planner,
@nyx/orbit-determination.
Cross-Domain Integration#
Nyx interoperates with the wider Oshun monorepo through
@nyx/lilith-integration, which surfaces cosmic-meditation content for the
Lilith consciousness domain. The @nyx/orbital library includes a
kalika-relativity module and a solar-system-integration module that provide
thin touchpoints with the Kalika mathematics/physics domain.
The boundary with Lilith is intentionally content-level rather than data-level: Lilith receives pre-composed meditation material (visualizations, breath patterns, awareness phases) rather than raw ephemeris data or catalog objects. This prevents Lilith from taking an indirect dependency on the entire astronomical computation stack.
The earlier specification claimed Kafka event publishing via
@oshun/event-busandnyx.*event contracts in@oshun/contracts. No such Kafka publisher orNyxEventTypescontract exists in the current code; that claim has been removed.
Configuration Reference#
Configuration is supplied through environment variables read at process startup;
there is no single NyxConfig object in code. The variables below are the
complete set observed across the API and pipeline source.
| Variable | Component | Effect |
|---|---|---|
PORT (default 3000) |
API | HTTP + WebSocket listen port |
HOST (default 0.0.0.0) |
API | Bind address |
WS_PATH (default /ws) |
API | WebSocket endpoint path |
NYX_REDIS_URL / REDIS_URL |
API | Redis backing for the rate limiter |
NYX_LOCAL_API_KEYS |
API | Comma-separated key:tier:owner local key entries |
NODE_ENV |
API/pipelines | Environment selection |
METRICS_ENABLED |
Pipelines | Set to false to disable the health/metrics server |
Tier rate limits, WebSocket tier limits, ping intervals, and pipeline registry
entries are defined as constants in code (RATE_LIMIT_TIERS,
DEFAULT_TIER_LIMITS, PIPELINES) rather than configuration.
Acceptance Criteria#
A change to the Nyx domain is acceptance-complete when all of the following conditions hold. They are ordered to mirror the dependency chain: types first, then API, then persistence, then tests.
- All
@nyx/typesexports type-check and consumers compile against them. - New API routes are defined with
@hono/zod-openapicreateRoute, validate input with Zod schemas, and return the standard success/ProblemDetailenvelopes. - New persistent entities are added both as Zod schema models in
@nyx/databaseand as Knex migrations, with the migration's table covered bymigrations/20260118000006_create_indexes.tswhere query patterns need indexes. - Astronomical computations are unit-tested with Vitest against known-correct reference values (eclipse contacts, planet positions, separation angles), not merely shape assertions.
- WebSocket message and channel additions extend
NyxMessageType/NyxChanneland respect the per-tierDEFAULT_TIER_LIMITS. - Pipeline changes preserve the independent-worker model and the shared health/metrics server.
npx tsc --noEmit,npx vitest run, and lint pass for each affected package.
Source Grounding#
This specification was reconstructed from source: libs/nyx/types/src/*
(coordinates, celestial, time, observer, orbital, visualization, index),
libs/nyx/database/src/schema/* and src/migrations/*, apps/nyx/api/src/*
(app, index, routes, schemas, middleware, websocket),
libs/nyx/events/src/index.ts,
libs/nyx/lilith-integration/src/lilith-integration.ts,
libs/nyx/constellations/src/index.ts, libs/nyx/sky-clock/src/*,
apps/nyx/pipelines/src/*, the 75 libs/nyx/**/package.json files, the 22
apps/nyx/**/package.json files, deploy/nyx/*, and TODOS/phase-21.md. Every
enum value, field, endpoint, table, and package name is present in that source.