Examples

Code examples for common use cases

Code Examples

Practical examples for common use cases.

Daily Quote Widget

Display a random quote that changes daily:

async function getDailyQuote() {
  // Use date as seed for consistent daily quote
  const today = new Date().toISOString().split('T')[0];
  const cacheKey = `daily-quote-${today}`;
  
  // Check localStorage cache
  const cached = localStorage.getItem(cacheKey);
  if (cached) return JSON.parse(cached);
  
  const response = await fetch(
    'https://quotegallery.nl/api/quotes?limit=1&random=true&language=en'
  );
  const { data } = await response.json();
  const quote = data[0];
  
  // Cache for the day
  localStorage.setItem(cacheKey, JSON.stringify(quote));
  return quote;
}

// Usage
const quote = await getDailyQuote();
console.log(`"${quote.translations[0].text}" - ${quote.author.name}`);

Infinite Scroll

Load quotes progressively without duplicates:

class QuoteLoader {
  constructor() {
    this.seenIds = [];
    this.hasMore = true;
    this.page = 1;
  }

  async loadNext(count = 10) {
    if (!this.hasMore) return [];

    const params = new URLSearchParams({
      limit: count.toString(),
      page: this.page.toString(),
      exclude_ids: this.seenIds.join(',')
    });

    const response = await fetch(
      `https://quotegallery.nl/api/v1/quotes?${params}`
    );
    const { data, pagination, meta } = await response.json();

    this.seenIds.push(...data.map(q => q.id));
    this.hasMore = pagination.hasMore;
    this.page++;

    // Reset if running low on unseen quotes
    if (meta.reset_exclusion) {
      this.reset();
    }

    return data;
  }

  reset() {
    this.seenIds = [];
    this.page = 1;
    this.hasMore = true;
  }
}

// Usage
const loader = new QuoteLoader();

// Initial load
const quotes = await loader.loadNext(10);

// Load more (e.g., on scroll)
const moreQuotes = await loader.loadNext(10);

Category Browser

Browse quotes by category:

const CATEGORIES = [
  'philosophical', 'scientific', 'literary', 
  'historical', 'contemporary', 'business'
];

async function getQuotesByCategory(category, page = 1) {
  const params = new URLSearchParams({
    category,
    page: page.toString(),
    limit: '10',
    sort: 'most_liked'
  });

  const response = await fetch(
    `https://quotegallery.nl/api/v1/quotes?${params}`
  );
  return response.json();
}

// Usage
const philosophicalQuotes = await getQuotesByCategory('philosophical');
console.log(`Found ${philosophicalQuotes.pagination.total} philosophical quotes`);

Search with Debouncing

Implement search with debouncing:

function debounce(func, wait) {
  let timeout;
  return (...args) => {
    clearTimeout(timeout);
    timeout = setTimeout(() => func(...args), wait);
  };
}

async function searchQuotes(query) {
  if (query.length < 2) return { results: [] };
  
  const params = new URLSearchParams({
    q: query,
    limit: '10',
    language: 'en'
  });

  const response = await fetch(
    `https://quotegallery.nl/api/v1/search?${params}`
  );
  return response.json();
}

// Usage with debouncing
const debouncedSearch = debounce(async (query) => {
  const results = await searchQuotes(query);
  console.log(results);
}, 300);

// In your input handler
input.addEventListener('input', (e) => {
  debouncedSearch(e.target.value);
});

React Hook

Custom React hook for quotes:

import { useState, useEffect } from 'react';

function useQuotes(options = {}) {
  const [quotes, setQuotes] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    async function fetchQuotes() {
      try {
        setLoading(true);
        const params = new URLSearchParams({
          limit: options.limit?.toString() || '10',
          ...options.category && { category: options.category },
          ...options.language && { language: options.language },
          ...options.random && { random: 'true' }
        });

        const response = await fetch(
          `https://quotegallery.nl/api/quotes?${params}`
        );
        
        if (!response.ok) throw new Error('Failed to fetch quotes');
        
        const { data } = await response.json();
        setQuotes(data);
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    }

    fetchQuotes();
  }, [options.limit, options.category, options.language, options.random]);

  return { quotes, loading, error };
}

// Usage
function QuoteList() {
  const { quotes, loading, error } = useQuotes({
    limit: 5,
    category: 'philosophical',
    language: 'en'
  });

  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error}</div>;

  return (
    <ul>
      {quotes.map(quote => (
        <li key={quote.id}>
          "{quote.translations[0].text}" - {quote.author.name}
        </li>
      ))}
    </ul>
  );
}

Vue Composable

Composable for Vue 3:

import { ref, onMounted } from 'vue';

export function useQuotes(options = {}) {
  const quotes = ref([]);
  const loading = ref(true);
  const error = ref(null);

  async function fetchQuotes() {
    try {
      loading.value = true;
      const params = new URLSearchParams({
        limit: options.limit?.toString() || '10',
        ...options.category && { category: options.category },
        ...options.language && { language: options.language }
      });

      const response = await fetch(
        `https://quotegallery.nl/api/quotes?${params}`
      );
      
      if (!response.ok) throw new Error('Failed to fetch');
      
      const { data } = await response.json();
      quotes.value = data;
    } catch (err) {
      error.value = err.message;
    } finally {
      loading.value = false;
    }
  }

  onMounted(fetchQuotes);

  return { quotes, loading, error, refetch: fetchQuotes };
}
<script setup>
const { quotes, loading, error } = useQuotes({
  limit: 5,
  category: 'philosophical'
});
</script>

<template>
  <div v-if="loading">Loading...</div>
  <div v-else-if="error">{{ error }}</div>
  <ul v-else>
    <li v-for="quote in quotes" :key="quote.id">
      "{{ quote.translations[0].text }}" - {{ quote.author.name }}
    </li>
  </ul>
</template>