Two ways the front end talks to data. REST gives you fixed URLs that return fixed shapes; GraphQL lets you ask for exactly the fields you want — no more, no less.
This makes a genuine fetch() over the network to the public JSONPlaceholder API. Pick an endpoint and hit Send — you'll see the actual JSON it returns.
const res = await fetch("https://jsonplaceholder.typicode.com/todos/1"); const data = await res.json(); console.log(data); // { userId, id, title, completed }
Notice that /users/1 returns the user's address, company, phone, website — even if your UI only needs the name. REST endpoints return a fixed shape, so you often download fields you'll never use. That's over-fetching.
This sends a genuine POST to the public, no-auth Countries GraphQL API. We ask for only name, capital and emoji — and that's exactly what comes back. Pick a country and run it.
const query = `query ($code: ID!) { country(code: $code) { name capital emoji } }`; await fetch("https://countries.trevorblades.com", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ query, variables: { code: "BG" } }) });
Same goal — "show me a country" — but two very different payloads.
You hit /country/BG and the server decides what comes back — name, region, population, currencies, languages, borders, timezones… You take it all, even to show one flag.
You write the query, so you receive only name, capital, emoji. Smaller payload, fewer round-trips, and the response shape mirrors your request exactly.
Neither is "better" — REST is simple, cacheable and everywhere; GraphQL shines when clients have varied, precise data needs.
fetch() against the live JSONPlaceholder API; the GraphQL demo POSTs a real query to the public, no-auth Countries API (countries.trevorblades.com). Both show the actual responses and fall back to a friendly message if you're offline. The shared CSS shell styles the surrounding page. — That's all 64 tools. Thanks for exploring the Academy! 🎓