1
Fork 0
country-explorer/app.js
Leonardo Devai 175e8a5867 Review and modernize all 42 projects to the updated standard
Pinned 2026 toolchains (Go 1.26, Rust 1.98/edition 2024, Python 3.14 + uv, Node 24,
Zig 0.16, NixOS 26.05), postgres 18 / mongo 8, lockfiles built from, non-root
runtimes, .dockerignore, per-project LICENSE, READMEs with the git.devai.io clone
line, checkout@v7 CI. Security fixes in the legacy Rust APIs (any-password login,
self-assigned admin, hard-coded JWT secret), JWT alg/exp/sub enforcement across the
blog series, safe markdown links in the frontends, and many smaller bugs — every
project was built, run and exercised end to end.

Adds scripts/publish.sh + a CI publish job that splits every folder into its own
repo at git.devai.io/templates/<folder>.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01128fhuZbgivaSJvtMf4s1G
2026-09-27 21:10:38 +02:00

84 lines
2.9 KiB
JavaScript

const form = document.getElementById("form");
const input = document.getElementById("query");
const country = document.getElementById("country");
const statusEl = document.getElementById("status");
async function search(name) {
statusEl.textContent = "Loading…";
country.hidden = true;
try {
const res = await fetch(`https://countries.dev/name/${encodeURIComponent(name)}`);
if (res.status === 404) {
statusEl.textContent = `No country found for "${name}".`;
return;
}
if (!res.ok) throw new Error(`countries.dev returned ${res.status}`);
// An ARRAY of every country whose name contains the search ("united" finds
// five). We show the first one.
const data = await res.json();
render(data[0]);
statusEl.textContent = "";
} catch (err) {
statusEl.textContent = "Something went wrong. Try again in a moment.";
console.error(err);
}
}
// One country is a RICH object: plain values, nested objects, arrays of objects,
// and fields that are sometimes null. Rendering it is picking each piece apart.
//
// {
// name: "Japan",
// capital: "Tokyo", // null for Antarctica
// population: 125836021,
// region: "Asia", subregion: "Eastern Asia",
// flags: { svg: "https://flagcdn.com/jp.svg" }, // an image URL
// languages: [{ name: "Japanese" }], // an array of objects
// currencies: [{ code: "JPY", name: "Japanese yen" }],
// latlng: [36, 138],
// }
function render(c) {
// The API hands us a URL; pointing an <img> at it is all it takes.
const flag = document.getElementById("flag");
flag.src = c.flags?.svg || "";
flag.alt = `Flag of ${c.name}`;
document.getElementById("name").textContent = c.name;
document.getElementById("region").textContent = c.subregion
? `${c.region} · ${c.subregion}`
: c.region;
document.getElementById("capital").textContent = c.capital || "—";
// toLocaleString adds the thousands separators: 125836021 → "125,836,021".
document.getElementById("population").textContent = c.population?.toLocaleString() || "—";
// Arrays of objects: map each object down to its .name, then join them.
document.getElementById("languages").textContent = c.languages?.length
? c.languages.map((lang) => lang.name).join(", ")
: "—";
document.getElementById("currencies").textContent = c.currencies?.length
? c.currencies.map((money) => money.name).join(", ")
: "—";
const map = document.getElementById("map");
if (Array.isArray(c.latlng) && c.latlng.length === 2) {
const [lat, lng] = c.latlng;
map.href = `https://www.openstreetmap.org/?mlat=${lat}&mlon=${lng}#map=5/${lat}/${lng}`;
map.hidden = false;
} else {
map.hidden = true;
}
country.hidden = false;
}
form.addEventListener("submit", (event) => {
event.preventDefault();
const name = input.value.trim();
if (name) search(name);
});
search("Japan");