Building SkyMoment: A 4K Personalized Star Map Generator with Python, Skyfield and Astronomical Data

Published: (December 6, 2025 at 03:47 PM EST)
3 min read
Source: Dev.to

Source: Dev.to

The idea

Most “star map posters” online aren’t based on real sky data; they use approximations, fake constellations, or pre‑rendered visuals. I wanted something more accurate and scientific:

  • Real positions of stars
  • Real coordinate transforms
  • Proper field of view
  • Natural‑looking Milky Way
  • Clean and minimal layout

…and turn it into a small automated product: enter a moment → get a PDF/PNG → done.

Tech stack overview

  • Python – main rendering pipeline
  • Skyfield – planetary ephemeris & star calculations
  • Hipparcos catalog – star positions & magnitudes
  • Astropy – coordinate transforms
  • Matplotlib – final 4K rendering
  • Django – backend & API
  • Lemon Squeezy – payments + webhooks
  • SMTP – email delivery of the final poster

The frontend is intentionally minimal; the “magic” happens in the rendering pipeline.

Astronomical calculations step‑by‑step

When a user enters a date, time, and location (lat/lon), the pipeline does:

  1. Convert local time to UTC – Skyfield requires accurate UTC timestamps.
  2. Load planetary ephemeris – using DE421 / DE422 depending on the build.
  3. Load Hipparcos star catalog – provides RA/Dec, magnitude, proper motion.
  4. Transform everything into the user’s sky coordinates – using Astropy AltAz transforms based on the observer’s position.
  5. Filter stars – only stars above a certain brightness threshold are rendered.
  6. Split bright/faint stars – bright stars use a stylized 8‑point marker; faint stars use simple dots.
  7. Render the Milky Way – a custom multi‑noise layer (low‑frequency shapes, medium cloud structure, smooth alpha falloff, suppression of “sand grain” artifacts). This part took the longest to tune.
  8. Render at 4000 × 4000 resolution – Matplotlib does a great job when used carefully.

Total render time: ~35–40 seconds on server hardware.

Rendering performance challenges

4K resolution + thousands of stars + Milky Way noise layers = heavy. Some optimizations:

  • Pre‑load catalogs once per worker
  • Reuse figure objects
  • Avoid expensive Python loops
  • Limit use of transparency
  • Skip stars below a certain magnitude
  • Cache static layers when possible

Even small changes can save 10–20 % time.

Backend architecture (Django)

SkyMoment uses a simple pipeline:

  1. User configures their moment – chooses date/time/location and sees a preview.
  2. User is redirected to Lemon Squeezy checkout.
  3. After payment, LS sends a webhook to Django – containing order ID, custom fields (title, location, datetime), and product variant.
  4. Django creates a generation job – status transitions: pendinggeneratingready.
  5. A worker process runs the Python renderer.
  6. The final 4K poster is saved to disk.
  7. Django sends an email with a download link.

Important detail: the webhook responds immediately; rendering happens asynchronously to avoid LS timeouts.

Example of what the system produces

Reduced‑size preview of a generated poster (insert image URL if desired).

The 4K version includes:

  • Precise star positions
  • Constellation lines
  • Minimal typography
  • Custom title & subtitle
  • Clean dark theme

What’s next

Roadmap items:

  • Multiple poster templates
  • Faster rendering (caching or partial reuse)
  • More curated landing pages
  • Detailed generation logs and analytics

If you want to try generating a star map for your own moment:

🔗

Happy to answer any technical questions about astronomical data, rendering, or backend architecture!

Back to Blog

Related posts

Read more »

Django: what’s new in 6.0

2025-12-03 !https://adamj.eu/tech/assets/2025-12-03-django-mosaic.webp Django 6.0 was released todayhttps://www.djangoproject.com/weblog/2025/dec/03/django-60-r...