Skip to main content
The home page fetches the top 20 cryptocurrencies ordered by market cap from the CoinGecko /coins/markets endpoint and renders them in a responsive table. Data is cached in localStorage for 5 minutes via keepInfo() to avoid unnecessary API calls on every page visit.

Data loading

The Home page component calls keepInfo() inside a useEffect on mount:
home.jsx
import { keepInfo } from "../services/cache";

export function Home() {
  const [crypto, setCrypto] = useState([]);

  useEffect(() => {
    async function loadCryptos() {
      const data = await keepInfo();
      setCrypto(data);
    }
    loadCryptos();
  }, []);
}
keepInfo() checks localStorage first. If a valid cache entry exists (less than 5 minutes old) it returns the cached result; otherwise it calls getTopCryptos(), which hits:
GET https://api.coingecko.com/api/v3/coins/markets
  ?vs_currency=usd
  &order=market_cap_desc
  &per_page=20
  &page=1

Table columns

The desktop table renders the following columns in order:
ColumnDescription
# (logo)Coin logo image sourced from CoinGecko
NameFull coin name (e.g. Bitcoin)
SymTicker symbol, displayed uppercased (e.g. BTC)
PriceCurrent price in USD
Volume24-hour total trading volume in USD
Market CapMarket capitalization in USD
Change 24hPrice change percentage over the last 24 hours, colored green (positive) or red (negative)
FavoritosStar icon button — click to toggle the coin as a favorite

CryptoCard component

Each row in the list is rendered by the CryptoCard component. It accepts the following props:
props.id
string
required
Unique CoinGecko coin identifier (e.g. "bitcoin", "ethereum"). Used as the key and as the favorites identifier.
props.symbol
string
required
Ticker symbol (e.g. "btc"). Displayed uppercased in the symbol column.
props.image
string
required
URL of the coin logo image sourced from CoinGecko.
props.name
string
required
Human-readable coin name (e.g. "Bitcoin").
props.marketCap
number
required
Market capitalization in USD. Formatted with formatter from formatNumbers.js.
props.volume
number
required
24-hour trading volume in USD. Formatted with formatter from formatNumbers.js.
props.price
number
required
Current price in USD. Formatted with formatter from formatNumbers.js.
props.change24h
number
required
Price change percentage over the last 24 hours. Displayed in green when positive, red when negative.

Currency formatting

All monetary values are formatted using the formatter instance exported from src/utils/formatNumbers.js:
formatNumbers.js
export const formatter = new Intl.NumberFormat("en-US", {
  maximumFractionDigits: 2,
  minimumFractionDigits: 2,
  style: "currency",
  currency: "USD",
});
This produces values like $45,231.00 and $1,234,567,890.00 consistently across all columns.

Responsive layout

The listing uses a two-layout approach controlled by Tailwind CSS breakpoints:
Each coin is rendered as a card with the logo, name, and symbol at the top, followed by a two-column grid showing price, volume, market cap, and 24h change. The favorite toggle appears in the top-right corner of the card.
The header row (#, Name, Sym, Price, …) is only visible on md and larger screens. The mobile card view shows the same data in a stacked grid layout.

Build docs developers (and LLMs) love