Back to projects No. 005 · Web app

ORBIT

I consume real APIs with modular JavaScript and async/await, and design loading, empty and error states so no wait is left blank.

Full ORBIT page: hero, astronomy picture of the day, search with filters, image gallery and About section
Year
2026
Type
Web app · API consumption
Role
Front-end design and development
Stack
HTML5 · Sass · JavaScript (ES modules) · Axios

Challenge, solution and result

The challenge

Real data, unpredictable responses

Consuming a real public API and presenting it clearly: any search can take a while, come back empty or fail, and the interface has to communicate each case.

The solution

A data layer and small modules

Requests with Axios and async/await, single-responsibility ES modules and an editorial design that lets the images take center stage.

The result

A published, accessible explorer

It shows the astronomy picture of the day, searches the NASA archive, filters by object type and opens each image in high resolution.

Highlights

What it does and how it works

01

Searching the NASA archive

Free-text search and quick filters for galaxies, nebulae, the Moon, Earth and missions. Each card is generated from an HTML template and opens a native modal with the high-resolution image.

ORBIT's Explore section with the search bar, filters and gallery
02

Clear states

Loading skeletons, empty results and a connection error with a retry button. No wait is left blank.

03

Designed for everyone

A skip-to-content link, visible keyboard focus, a modal using <dialog> and support for reduced motion.

A technical decision

No slow response overwrites a newer one

If someone searches for "galaxies" and right after for "nebulae", the first response may arrive after the second and show the wrong results.

Each search gets a number (requestId). When a response arrives, it's only shown if it's still the most recent; the others are discarded.

js/main.js · simplified
let requestId = 0;

async function runSearch(query) {
  const id = ++requestId;
  showState('loading');

  try {
    const items = await searchImages(query);
    // Arrived late: there's already a newer search.
    if (id !== requestId) return;

    renderCards(items, openModal);
    showState(items.length ? 'results' : 'empty');
  } catch (error) {
    if (id !== requestId) return;
    showState('error');
  }
}
What it shows

Images: NASA, JPL and GSFC. ORBIT is an independent project, not affiliated with NASA.

Next project Aula Accesible