DEV Community

Doushabao
Doushabao

Posted on

I Built a "Today in History" Feature Using 3 Free APIs — Here's the Code

I Built a "Today in History" Feature Using 3 Free APIs — Here's the Code

Last week I wanted to add a "Today in History" section to a side project — you know, that little widget showing what happened on this date, random space facts, and recent earthquakes. The kind of thing that makes a boring homepage feel alive.

The problem? Every tutorial I found used a single API. I wanted something richer. So I combined three free APIs that nobody talks about together, and the result was surprisingly good.

Here's exactly how I did it.

Why Three APIs?

Most "history on this day" pages are flat — just a list of events. I wanted:

  1. Historical events — what happened on this date
  2. Space facts — because who doesn't love random NASA trivia
  3. Recent earthquakes — real-time natural disaster data

Each of these serves a different purpose, and together they create a daily digest that's actually worth reading.

API 1: Historical Events

The on-this-day API returns events, births, deaths, and holidays for any date. No API key needed, no rate limit headaches.

async function getHistoryEvents() {
  const today = new Date();
  const month = today.getMonth() + 1;
  const day = today.getDate();

  const response = await fetch(
    `https://api.quotalink.cn/api/v1/on-this-day?month=${month}&day=${day}`
  );
  const data = await response.json();

  return data.events || [];
}
Enter fullscreen mode Exit fullscreen mode

The response includes events, births, deaths, and holidays. I usually grab 3-5 events and 2-3 births to keep the digest concise.

API 2: Space Facts

This one's my favorite. The space-science API gives you random space facts, NASA's picture of the day, and ISS location data. Perfect for that "did you know?" section.

async function getSpaceFact() {
  const response = await fetch(
    'https://api.quotalink.cn/api/v1/space-science/fact'
  );
  const data = await response.json();

  return data.fact || 'Space is really big.';
}
Enter fullscreen mode Exit fullscreen mode

I also pull NASA's Astronomy Picture of the Day for a visual element:

async function getNasaImage() {
  const NASA_KEY = 'YOUR_NASA_API_KEY'; // free at api.nasa.gov
  const response = await fetch(
    `https://api.nasa.gov/planetary/apod?api_key=${NASA_KEY}`
  );
  const data = await response.json();

  return {
    title: data.title,
    url: data.url,
    explanation: data.explanation
  };
}
Enter fullscreen mode Exit fullscreen mode

API 3: Earthquake Data

The earthquake API pulls recent seismic activity from USGS data. It's not something you'd check every day, but when there's a significant event, users appreciate seeing it.

async function getRecentEarthquakes() {
  const response = await fetch(
    'https://api.quotalink.cn/api/v1/earthquake/recent?limit=5&min_magnitude=4.0'
  );
  const data = await response.json();

  return data.earthquakes || [];
}
Enter fullscreen mode Exit fullscreen mode

Filtering by minimum magnitude (4.0+) keeps the list manageable — nobody needs to know about every tiny tremor.

Putting It All Together

Here's the combined function that builds the daily digest:

async function buildDailyDigest() {
  const [events, spaceFact, earthquakes] = await Promise.all([
    getHistoryEvents(),
    getSpaceFact(),
    getRecentEarthquakes()
  ]);

  return {
    date: new Date().toLocaleDateString('en-US', { 
      weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' 
    }),
    history: events.slice(0, 3),
    space: spaceFact,
    disasters: earthquakes.filter(eq => eq.magnitude >= 4.5)
  };
}

// Usage
buildDailyDigest().then(digest => {
  console.log(`📅 ${digest.date}`);
  console.log('\n📜 On This Day:');
  digest.history.forEach(e => console.log(`  • ${e.year}: ${e.text}`));
  console.log(`\n🚀 Space Fact: ${digest.space}`);
  console.log('\n🌍 Recent Earthquakes:');
  digest.disasters.forEach(eq => 
    console.log(`  • M${eq.magnitude}${eq.location}`)
  );
});
Enter fullscreen mode Exit fullscreen mode

Error Handling (The Part Nobody Talks About)

Free APIs go down. Here's how I handle it without breaking the whole digest:

async function safeFetch(url, fallback = null) {
  try {
    const controller = new AbortController();
    const timeout = setTimeout(() => controller.abort(), 5000);

    const response = await fetch(url, { signal: controller.signal });
    clearTimeout(timeout);

    if (!response.ok) throw new Error(`HTTP ${response.status}`);
    return await response.json();
  } catch (err) {
    console.warn(`API call failed: ${url}${err.message}`);
    return fallback;
  }
}
Enter fullscreen mode Exit fullscreen mode

I use this wrapper for every API call. If one service is down, the digest still renders with the other two.

Caching Strategy

You don't want to hit these APIs on every page load. I cache the digest for 6 hours:

const cache = new Map();

async function getCachedDigest() {
  const cacheKey = `digest-${new Date().toISOString().slice(0, 10)}`;

  if (cache.has(cacheKey)) {
    return cache.get(cacheKey);
  }

  const digest = await buildDailyDigest();
  cache.set(cacheKey, digest);

  // Auto-expire after 6 hours
  setTimeout(() => cache.delete(cacheKey), 6 * 60 * 60 * 1000);

  return digest;
}
Enter fullscreen mode Exit fullscreen mode

What I Learned

Three things surprised me:

  1. Combining APIs creates more value than any single one. The historical events alone are boring. Add a space fact and recent earthquakes, and suddenly it's a daily ritual.

  2. Free APIs have personality. The space facts API returns genuinely interesting tidbits. The earthquake data has a certain gravity (pun intended) that makes users check back.

  3. Error handling is the real product. The difference between a hacky demo and something people actually use is how gracefully it handles API failures.

Try It Yourself

All three APIs I used are free and require no registration:

  • Historical events: GET /api/v1/on-this-day?month=9&day=1
  • Space facts: GET /api/v1/space-science/fact
  • Earthquake data: GET /api/v1/earthquake/recent?limit=5

You can test them directly in your browser or with curl. No API key, no sign-up, no credit card.

Next Steps

I'm planning to add:

  • Weather overlay — show the weather for each historical event's location
  • News aggregation — pull today's top headlines for context
  • Random name generator — for the "People Born Today" section (instead of just famous people)

If you build something with these APIs, I'd love to see it. Drop a comment below or open an issue on the repo.


Found this useful? I write about API integration and side project engineering. Follow for more tutorials that actually work in production, not just in demos.

Top comments (0)