Freedom Sale
Independence Day Special — Unlock the AI Path 70% off our most popular AI course · Limited time offer
--Days
--Hrs
--Min
--Sec
Claim Your Discount
✦ Beginner ⏱ 20 min

💬 Build a Random Quote Generator

🎯 What You'll Build

A stylish random quote generator that fetches quotes from a free public API, displays them with a fade animation, and lets you share them on Twitter/X.

📋 What You'll Need

1

Fetch a quote from a free API

quotable.io provides a free API with 1,000+ curated quotes — no key needed.

async function getQuote() {
  const res  = await fetch('https://api.quotable.io/random');
  const data = await res.json();
  console.log(data.content);      // "Life is what happens when..."
  console.log(data.author);       // "John Lennon"
}

getQuote();
2

Build the full HTML page

Card layout, a quote block, author line, and two action buttons.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Random Quote Generator</title>
  <style>
    * { margin:0; padding:0; box-sizing:border-box; }
    body { font-family:'Segoe UI',sans-serif; background:linear-gradient(135deg,#1e3a5f,#162032); min-height:100vh; display:flex; align-items:center; justify-content:center; padding:20px; }
    .card { background:#fff; color:#1e293b; border-radius:20px; padding:48px 44px; max-width:580px; width:100%; box-shadow:0 25px 60px rgba(0,0,0,0.35); }
    .quote-mark { font-size:5rem; line-height:1; color:#e2e8f0; font-family:Georgia,serif; margin-bottom:-20px; }
    #quote { font-size:1.3rem; line-height:1.7; font-style:italic; color:#334155; margin-bottom:20px; transition:opacity 0.4s; }
    #author { font-weight:700; color:#0f172a; font-size:1rem; margin-bottom:32px; }
    #author::before { content:'— '; color:#94a3b8; }
    .actions { display:flex; gap:12px; }
    .btn-new   { flex:1; padding:12px; background:#1e3a5f; color:#fff; border:none; border-radius:10px; font-size:0.95rem; font-weight:700; cursor:pointer; transition:background 0.2s; }
    .btn-new:hover { background:#162032; }
    .btn-tweet { padding:12px 20px; background:#1DA1F2; color:#fff; border:none; border-radius:10px; font-size:0.95rem; font-weight:700; cursor:pointer; text-decoration:none; display:flex; align-items:center; gap:6px; }
    .loading { opacity:0.3; }
  </style>
</head>
<body>

<?php require_once __DIR__ . '/../promo_banner.php'; ?>

  <div class="card">
    <div class="quote-mark">"</div>
    <p id="quote">Loading...</p>
    <p id="author"></p>
    <div class="actions">
      <button class="btn-new" onclick="loadQuote()">New Quote</button>
      <a class="btn-tweet" id="tweetBtn" href="#" target="_blank">Tweet</a>
    </div>
  </div>
  <script src="app.js"></script>
</body>
</html>
3

Fetch and display quotes with a fade animation

Fade the quote out, update it, then fade back in.

// app.js
const quoteEl  = document.getElementById('quote');
const authorEl = document.getElementById('author');
const tweetBtn = document.getElementById('tweetBtn');

async function loadQuote() {
  quoteEl.classList.add('loading');

  try {
    const res  = await fetch('https://api.quotable.io/random');
    const data = await res.json();

    // Fade in new content
    setTimeout(() => {
      quoteEl.textContent  = data.content;
      authorEl.textContent = data.author;
      tweetBtn.href = `https://twitter.com/intent/tweet?text=${encodeURIComponent('"' + data.content + '" — ' + data.author)}`;
      quoteEl.classList.remove('loading');
    }, 300);

  } catch (err) {
    quoteEl.textContent = 'Could not load a quote. Check your connection.';
    quoteEl.classList.remove('loading');
  }
}

// Load on page open
loadQuote();
💡 Tip: The Quotable API supports filtering by tag and author. Try fetch("https://api.quotable.io/random?tags=technology") for tech quotes, or filter by minLength and maxLength to keep quotes tweet-sized.

🎉 You Did It!

Your first API-powered app. The same fetch() pattern works with any JSON API — weather, movies, jokes, exchange rates. Change the API URL and adjust the display code for any data source.

Found something wrong?

Spotted a bug, broken code, or something that doesn't look right? Tell us what's off and we'll fix it.