Sitelet https://github.com/a7bdev/falak/blob/main/CONTRIBUTING.md
Skip to content

Latest commit

Β 

History

History
157 lines (125 loc) Β· 6.92 KB

File metadata and controls

157 lines (125 loc) Β· 6.92 KB

Contributing to Falak (فلك)

Thanks for wanting to help! Falak is intentionally tiny β€” please help keep it that way. This document covers the ground rules, how to run the project locally, the backend module contract, and step-by-step guides for the two most welcome contributions: adding a language and improving a data catalog.

Ground rules

These are the project's identity, not preferences. PRs that break them will be declined regardless of quality:

  1. One dependency. The backend must stay Python 3 + ephem only. No numpy, no flask, no requests, no astropy/skyfield. The web server is the Python standard library.
  2. Offline-first is non-negotiable. No CDN assets, no external JS or fonts, no telemetry, no API keys, no accounts. Any feature that needs the network must degrade gracefully without it and disclose where its data came from and how old it is β€” the TLE pipeline in backend/satellites.py (source: network|cache|none + tle_age_hours) is the reference pattern.
  3. Data honesty. Never present an estimate as a measurement. If Falak can't know something from geometry alone, it labels the limitation (see backend/tides.py, which returns "type": "astronomical_estimate").
  4. The frontend stays self-contained. Plain HTML/CSS/JS, no build step, no frameworks, all assets served from disk.

Running locally

git clone <your-fork> falak && cd falak
pip install -r requirements.txt    # just: ephem
python3 backend/server.py          # serves http://127.0.0.1:8091

Then run the smoke tests β€” they must pass fully offline (the suite stubs the network itself):

python3 tests/test_smoke.py        # or: python3 -m pytest tests/

The tests import every backend module, build a Dubai observer at a fixed UTC instant, call each compute(), and assert the documented response shapes. If you add a module, key, or reason code, extend the smoke test in the same PR.

The backend module contract

Full detail in docs/ARCHITECTURE.md; the short form:

Every compute module in backend/ exposes exactly one entry point:

compute(obs, when_utc) -> dict
  • obs is an ephem.Observer built by core.make_observer(...) β€” core.py is the only place observers are constructed. Beware the classic PyEphem trap: lat/lon/RA/Dec must be assigned as strings (parsed as degrees / sexagesimal); raw floats are read as radians.
  • when_utc is a naive datetime treated as UTC. The backend never localizes: all times in responses are ISO 8601 UTC strings; angles are float degrees. tz= is echoed back untouched and applied client-side.
  • Return a plain, JSON-serializable dict. No ephem.Date/ephem.Angle objects may leak out β€” convert at the boundary with core.iso() / core.deg().
  • PyEphem search calls (next_rising, horizon tweaks, …) mutate observer state. If your module scans, work on core.clone(obs), never the instance you were handed.
  • Do not print. Do not raise for expected conditions β€” return a valid dict (an empty pass list, an up: false, …). server.py wraps each slot in try/except so an unexpected exception poisons only your card, but that is a safety net, not a license.
  • Keys are language-neutral English snake_case tokens, never sentences β€” the frontend does all i18n (see below).

Code style

  • Backend: stdlib style, small functions, comments where the math is non-obvious (cite a source for astronomical formulas or criteria β€” e.g. Odeh/Yallop for the crescent, depression angles for prayer times).
  • Frontend: vanilla JS, no build step. Every human-visible string goes through frontend/i18n.js β€” never hard-code display text in index.html/skymap.js.
  • Emitted "reasons" are structured, e.g. {"code": "planet", "planet": "saturn", "alt": 42}, never prose. The frontend fills templates from the active language's token map. The smoke test enforces this shape.
  • One topic per PR, with a clear description. Small and focused beats big and clever.

Adding a language

The whole UI for a language is one self-contained block in frontend/i18n.js (window.I18N). Currently: ar, en, fr, es, ur, hi, tr, zh (ar/ur RTL).

  1. Copy the en block to your language code and translate every entry. A language must carry the complete key set β€” both:
    • flat keys for static UI text (s_moon, best_window, err_slot, …), and
    • token maps β€” the sub-dictionaries keyed by backend tokens: phases, planets, prayers, cardinal, compass, twilight_names, planet_notes, bw, and the tonight reason templates.
  2. For right-to-left languages, set dir: "rtl" in the block β€” the page and the sky map flip automatically.
  3. Check the rendered result in both themes; docs/qa/ holds per-language screenshots you can compare against.
  4. If your language needs a font the bundled stack (Alexandria, Noto Kufi Arabic, Inter) doesn't cover, open an issue first β€” fonts are vendored locally as woff2 and we keep the payload lean.

Corollary rule for backend contributors: adding a new backend note/reason code means adding it to every language's token map in the same commit.

Adding to a data catalog

The bundled catalogs live in data/ and ship with the repo:

File Contents
cities.json Seed cities for the location picker (366 today)
star_names.json Bright stars, incl. traditional Arabic names
constellation_names.json Constellation names
meteor_showers.json Annual shower calendar (activity window, peak, ZHR)

Guidelines:

  • Match the existing entry shape exactly (open the file β€” they're small).
  • Cite a source in the PR description for astronomical data: IMC/IMO for showers, standard catalogs for stars, etc.
  • Coordinates in decimal degrees; keep city entries to notable/distinct locations rather than exhaustive coverage.
  • data/tle_cache.json is a runtime cache, not a catalog β€” don't edit or commit changes to it.

Also especially welcome: corrections to prayer-time methods and crescent criteria (with sources), and astronomy accuracy fixes of any kind.

Reporting bugs

Use the bug report template. Because everything is computed from your position and time, a useful report includes your approximate latitude/longitude, the UTC time, and expected vs. observed values (a screenshot helps).

Pull-request checklist

  • python3 tests/test_smoke.py passes, offline
  • No new runtime dependency, no network call without cache + disclosure
  • New strings/tokens present in all 8 language blocks
  • Angles in degrees, times in ISO 8601 UTC, keys in snake_case
  • One topic, clear description, sources cited for astronomical data

License

By contributing you agree your work is licensed under the project's MIT License.