Science — Open Data / Dataset Portal Landing
A government open-data portal homepage rendered as a single self-contained static page. It pairs a prominent search hero advertising 4,217 open datasets with clickable example-query chips, category tiles for Climate, Genomics, Economics, and Astronomy, and a filterable featured-datasets table showing format, size, license, and update columns with download buttons. A developer access panel offers tabbed, copyable cURL, Python, and JavaScript snippets, and animated usage counters round out the technical, no-nonsense layout.
MCP
Code
:root {
--bg: #ffffff;
--bg-alt: #f1f5f4;
--ink: #0f1b2d;
--ink-2: #33445c;
--muted: #697892;
--accent: #1f7a4d;
--accent-d: #176039;
--accent-50: #e7f3ec;
--slate: #334155;
--slate-2: #475569;
--mono-bg: #0f1b2d;
--line: rgba(15, 27, 45, 0.12);
--line-2: rgba(15, 27, 45, 0.2);
--ok: #2f9e6f;
--warn: #c9821f;
--danger: #cf4538;
--r-sm: 6px;
--r-md: 10px;
--r-lg: 16px;
--sh-1: 0 1px 2px rgba(15, 27, 45, 0.06), 0 1px 3px rgba(15, 27, 45, 0.05);
--sh-2: 0 4px 14px rgba(15, 27, 45, 0.08);
--mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
--sans: "Inter", system-ui, -apple-system, sans-serif;
--serif: "Source Serif 4", Georgia, serif;
}
* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
margin: 0;
font-family: var(--sans);
color: var(--ink);
background: var(--bg);
line-height: 1.6;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
}
h1, h2, h3 { line-height: 1.2; margin: 0; }
a { color: inherit; text-decoration: none; }
.wrap { width: 100%; max-width: 1120px; margin: 0 auto; padding: 0 24px; }
.sr-only {
position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.skip {
position: absolute; left: -999px; top: 8px; z-index: 100;
background: var(--accent); color: #fff; padding: 8px 14px; border-radius: var(--r-sm);
}
.skip:focus { left: 16px; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 3px; }
/* ---------- buttons ---------- */
.btn {
font-family: var(--sans); font-weight: 600; font-size: 14px;
border: 1px solid transparent; border-radius: var(--r-sm);
padding: 9px 16px; cursor: pointer; transition: all .15s ease;
display: inline-flex; align-items: center; gap: 7px; white-space: nowrap;
}
.btn-accent { background: var(--accent); color: #fff; }
.btn-accent:hover { background: var(--accent-d); }
.btn-accent:active { transform: translateY(1px); }
.btn-ghost { background: transparent; color: var(--ink-2); border-color: var(--line-2); }
.btn-ghost:hover { background: var(--bg-alt); color: var(--ink); }
/* ---------- topbar ---------- */
.topbar {
position: sticky; top: 0; z-index: 40;
background: rgba(255, 255, 255, 0.88); backdrop-filter: blur(10px);
border-bottom: 1px solid var(--line);
}
.topbar-in { display: flex; align-items: center; gap: 22px; height: 60px; }
.brand { display: inline-flex; align-items: center; gap: 9px; font-weight: 700; font-size: 17px; letter-spacing: -0.02em; }
.brand-mark { fill: var(--accent); }
.brand-txt { color: var(--ink); }
.brand-dot { color: var(--muted); font-weight: 600; }
.topnav { display: flex; gap: 22px; margin-left: 10px; }
.topnav a { font-size: 14px; font-weight: 500; color: var(--ink-2); transition: color .15s; }
.topnav a:hover { color: var(--accent); }
.topbar-actions { margin-left: auto; display: flex; align-items: center; gap: 14px; }
.status-pill {
display: inline-flex; align-items: center; gap: 6px;
font-family: var(--mono); font-size: 11px; color: var(--accent-d);
background: var(--accent-50); border: 1px solid rgba(31, 122, 77, 0.2);
padding: 4px 9px; border-radius: 999px;
}
.status-pill .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--ok); box-shadow: 0 0 0 3px rgba(47, 158, 111, 0.18); }
/* ---------- hero ---------- */
.hero {
background:
linear-gradient(180deg, var(--bg) 0%, var(--bg-alt) 100%),
repeating-linear-gradient(0deg, transparent, transparent 31px, var(--line) 31px, var(--line) 32px),
repeating-linear-gradient(90deg, transparent, transparent 31px, var(--line) 31px, var(--line) 32px);
background-blend-mode: normal, multiply, multiply;
border-bottom: 1px solid var(--line);
}
.hero-in { padding: 64px 24px 56px; }
.kicker {
font-family: var(--mono); font-size: 12px; letter-spacing: 0.04em;
text-transform: uppercase; color: var(--accent-d); margin: 0 0 14px;
}
.hero h1 {
font-family: var(--serif); font-weight: 700; font-size: clamp(32px, 5vw, 52px);
letter-spacing: -0.02em; color: var(--ink); margin-bottom: 16px;
}
.hero h1 .count { color: var(--accent); font-family: var(--mono); font-weight: 500; font-size: 0.92em; }
.lede { font-family: var(--serif); font-size: 18px; color: var(--ink-2); max-width: 640px; margin: 0 0 28px; }
.search {
display: flex; align-items: center; gap: 8px; max-width: 700px;
background: var(--bg); border: 1.5px solid var(--line-2); border-radius: var(--r-md);
padding: 7px 7px 7px 14px; box-shadow: var(--sh-1); transition: border-color .15s, box-shadow .15s;
}
.search:focus-within { border-color: var(--accent); box-shadow: 0 0 0 4px var(--accent-50); }
.search-ico { stroke: var(--muted); fill: none; stroke-width: 2; flex: none; }
.search input {
flex: 1; border: 0; outline: 0; background: transparent;
font-family: var(--sans); font-size: 15px; color: var(--ink); min-width: 0;
}
.search input::placeholder { color: var(--muted); }
.chips { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 16px; }
.chips-label { font-size: 13px; color: var(--muted); font-weight: 500; }
.chip {
font-family: var(--mono); font-size: 12px; color: var(--slate);
background: var(--bg); border: 1px solid var(--line-2); border-radius: 999px;
padding: 5px 12px; cursor: pointer; transition: all .15s;
}
.chip:hover { border-color: var(--accent); color: var(--accent-d); background: var(--accent-50); }
/* ---------- sections ---------- */
.section { padding: 56px 0; }
.section.alt { background: var(--bg-alt); border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }
.sec-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; margin-bottom: 26px; flex-wrap: wrap; }
.sec-head h2 { font-family: var(--serif); font-size: 26px; font-weight: 700; letter-spacing: -0.01em; }
.link-more { font-size: 14px; font-weight: 600; color: var(--accent); }
.link-more:hover { color: var(--accent-d); text-decoration: underline; }
/* ---------- category tiles ---------- */
.cat-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; }
.tile {
display: flex; align-items: center; gap: 14px; text-align: left;
background: var(--bg); border: 1px solid var(--line); border-radius: var(--r-md);
padding: 18px; cursor: pointer; transition: all .18s ease; font-family: var(--sans);
}
.tile:hover { border-color: var(--accent); box-shadow: var(--sh-2); transform: translateY(-2px); }
.tile-ico {
flex: none; width: 44px; height: 44px; border-radius: var(--r-sm);
display: grid; place-items: center;
}
.tile-ico svg { fill: none; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.tile-ico.clim { background: #e3f0f8; } .tile-ico.clim svg { stroke: #1a4f8a; }
.tile-ico.geno { background: var(--accent-50); } .tile-ico.geno svg { stroke: var(--accent-d); }
.tile-ico.econ { background: #fdf0e0; } .tile-ico.econ svg { stroke: var(--warn); }
.tile-ico.astro { background: #efeafa; } .tile-ico.astro svg { stroke: #6d4fc4; }
.tile-body { display: flex; flex-direction: column; min-width: 0; }
.tile-name { font-weight: 600; font-size: 15px; color: var(--ink); }
.tile-meta { font-family: var(--mono); font-size: 12px; color: var(--muted); margin-top: 3px; }
.tile-meta b { color: var(--ink-2); font-weight: 500; }
/* ---------- featured table ---------- */
.filter { display: flex; gap: 6px; flex-wrap: wrap; }
.fbtn {
font-family: var(--sans); font-size: 13px; font-weight: 500; color: var(--slate);
background: var(--bg); border: 1px solid var(--line-2); border-radius: var(--r-sm);
padding: 6px 13px; cursor: pointer; transition: all .15s;
}
.fbtn:hover { border-color: var(--accent); color: var(--accent-d); }
.fbtn.active { background: var(--ink); color: #fff; border-color: var(--ink); }
.table-scroll { overflow-x: auto; border: 1px solid var(--line); border-radius: var(--r-md); background: var(--bg); }
.dtable { width: 100%; border-collapse: collapse; min-width: 720px; }
.dtable thead th {
text-align: left; font-size: 11px; font-weight: 600; letter-spacing: 0.05em;
text-transform: uppercase; color: var(--muted);
padding: 13px 16px; background: var(--bg-alt); border-bottom: 1px solid var(--line);
}
.dtable th.num, .dtable td.num { text-align: right; font-family: var(--mono); }
.dtable th.ar, .dtable td.ar { text-align: right; }
.dtable tbody td { padding: 14px 16px; border-bottom: 1px solid var(--line); font-size: 14px; vertical-align: middle; }
.dtable tbody tr:last-child td { border-bottom: 0; }
.dtable tbody tr { transition: background .12s; }
.dtable tbody tr:hover { background: var(--accent-50); }
.ds-name { display: flex; flex-direction: column; gap: 3px; }
.ds-title { font-weight: 600; color: var(--ink); }
.ds-doi { font-family: var(--mono); font-size: 11px; color: var(--muted); }
.cat-tag {
display: inline-block; font-size: 11px; font-weight: 600; padding: 2px 8px;
border-radius: 999px; margin-right: 6px; font-family: var(--sans);
}
.cat-tag.Climate { background: #e3f0f8; color: #1a4f8a; }
.cat-tag.Genomics { background: var(--accent-50); color: var(--accent-d); }
.cat-tag.Economics { background: #fdf0e0; color: #9a6310; }
.cat-tag.Astronomy { background: #efeafa; color: #5a3fb0; }
.fmt-badge {
font-family: var(--mono); font-size: 11px; color: var(--slate);
background: var(--bg-alt); border: 1px solid var(--line); border-radius: var(--r-sm);
padding: 2px 7px;
}
.lic { font-family: var(--mono); font-size: 12px; color: var(--ink-2); }
.upd { font-family: var(--mono); font-size: 12px; color: var(--muted); }
.dl-btn {
font-family: var(--sans); font-size: 13px; font-weight: 600; color: var(--accent-d);
background: var(--bg); border: 1px solid var(--accent); border-radius: var(--r-sm);
padding: 6px 12px; cursor: pointer; display: inline-flex; align-items: center; gap: 6px;
transition: all .15s;
}
.dl-btn svg { stroke: currentColor; fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.dl-btn:hover { background: var(--accent); color: #fff; }
.table-foot { font-family: var(--mono); font-size: 12px; color: var(--muted); margin: 14px 2px 0; }
/* ---------- api panel ---------- */
.api-grid { display: grid; grid-template-columns: 0.85fr 1.15fr; gap: 42px; align-items: start; }
.api-copy h2 { font-family: var(--serif); font-size: 28px; font-weight: 700; margin-bottom: 14px; }
.api-feats { list-style: none; padding: 0; margin: 22px 0 0; display: grid; gap: 12px; }
.api-feats li { display: flex; align-items: center; gap: 11px; font-size: 14px; color: var(--ink-2); }
.fdot { width: 8px; height: 8px; border-radius: 50%; flex: none; }
.fdot.ok { background: var(--ok); box-shadow: 0 0 0 3px rgba(47, 158, 111, 0.16); }
.api-panel { border: 1px solid var(--line); border-radius: var(--r-lg); overflow: hidden; box-shadow: var(--sh-2); background: var(--bg); }
.api-tabs { display: flex; gap: 0; background: var(--bg-alt); border-bottom: 1px solid var(--line); }
.atab {
font-family: var(--sans); font-size: 13px; font-weight: 600; color: var(--muted);
background: transparent; border: 0; border-bottom: 2px solid transparent;
padding: 12px 18px; cursor: pointer; transition: all .15s;
}
.atab:hover { color: var(--ink-2); }
.atab.active { color: var(--accent-d); border-bottom-color: var(--accent); background: var(--bg); }
.api-code { background: var(--mono-bg); }
.api-code-top {
display: flex; align-items: center; justify-content: space-between; gap: 12px;
padding: 12px 16px; border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}
.api-endpoint { font-family: var(--mono); font-size: 12px; color: #8fd9b0; }
.copy-btn {
font-family: var(--sans); font-size: 12px; font-weight: 600; color: #cdd7e4;
background: rgba(255, 255, 255, 0.07); border: 1px solid rgba(255, 255, 255, 0.14);
border-radius: var(--r-sm); padding: 5px 10px; cursor: pointer;
display: inline-flex; align-items: center; gap: 6px; transition: all .15s;
}
.copy-btn svg { stroke: currentColor; fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.copy-btn:hover { background: rgba(255, 255, 255, 0.13); color: #fff; }
.copy-btn.done { background: rgba(47, 158, 111, 0.25); border-color: rgba(47, 158, 111, 0.5); color: #aef0cc; }
.code {
margin: 0; padding: 18px 16px; overflow-x: auto;
font-family: var(--mono); font-size: 13px; line-height: 1.7; color: #e6edf5;
}
.code .tok-cmd { color: #8fd9b0; } .code .tok-flag { color: #c9a0ff; }
.code .tok-url { color: #7cc4ff; } .code .tok-str { color: #f0c987; }
.code .tok-com { color: #6c7d93; } .code .tok-kw { color: #ff9eb1; }
.api-resp { display: flex; align-items: center; gap: 12px; padding: 11px 16px; border-top: 1px solid var(--line); background: var(--bg-alt); }
.resp-status { font-family: var(--mono); font-size: 12px; font-weight: 500; color: var(--ok); }
.resp-meta { font-family: var(--mono); font-size: 12px; color: var(--muted); }
/* ---------- stats ---------- */
.stat-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; }
.stat {
background: var(--bg); border: 1px solid var(--line); border-radius: var(--r-md);
padding: 26px 22px; text-align: center;
}
.stat-num { display: block; font-family: var(--mono); font-size: 34px; font-weight: 500; color: var(--accent-d); letter-spacing: -0.02em; }
.stat-lbl { display: block; font-size: 13px; color: var(--muted); margin-top: 6px; font-weight: 500; }
/* ---------- footer ---------- */
.footer { background: var(--mono-bg); color: #c2cdda; padding: 48px 0 24px; }
.footer-in { display: grid; grid-template-columns: 1.2fr 2fr; gap: 40px; padding-bottom: 36px; border-bottom: 1px solid rgba(255, 255, 255, 0.1); }
.footer .brand-txt { color: #fff; }
.footer .brand-dot { color: #7d8da3; }
.footer .brand-mark { fill: #4fbd83; }
.foot-note { font-size: 14px; color: #8b9aae; margin: 14px 0 0; max-width: 320px; }
.foot-cols { display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; }
.foot-col h3 { font-size: 12px; text-transform: uppercase; letter-spacing: 0.05em; color: #7d8da3; margin-bottom: 12px; }
.foot-col a { display: block; font-size: 14px; color: #c2cdda; padding: 4px 0; transition: color .15s; }
.foot-col a:hover { color: #fff; }
.foot-bottom { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding-top: 22px; font-size: 13px; color: #8b9aae; flex-wrap: wrap; }
.foot-base { font-family: var(--mono); font-size: 12px; color: #8fd9b0; background: rgba(255, 255, 255, 0.06); padding: 4px 9px; border-radius: var(--r-sm); }
/* ---------- toast ---------- */
.toast {
position: fixed; left: 50%; bottom: 28px; transform: translate(-50%, 20px);
background: var(--ink); color: #fff; font-size: 14px; font-weight: 500;
padding: 11px 20px; border-radius: var(--r-md); box-shadow: var(--sh-2);
opacity: 0; pointer-events: none; transition: all .25s ease; z-index: 80;
}
.toast.show { opacity: 1; transform: translate(-50%, 0); }
/* ---------- responsive ---------- */
@media (max-width: 900px) {
.cat-grid { grid-template-columns: repeat(2, 1fr); }
.api-grid { grid-template-columns: 1fr; gap: 28px; }
.stat-grid { grid-template-columns: repeat(2, 1fr); }
.footer-in { grid-template-columns: 1fr; gap: 28px; }
}
@media (max-width: 640px) {
.wrap { padding: 0 16px; }
.topnav { display: none; }
.hero-in { padding: 44px 16px 40px; }
.search { flex-wrap: wrap; }
.search input { min-width: 120px; }
.section { padding: 40px 0; }
.cat-grid { grid-template-columns: 1fr; }
.stat-grid { grid-template-columns: 1fr; }
.foot-cols { grid-template-columns: 1fr 1fr; }
.status-pill { display: none; }
}(function () {
"use strict";
/* ---------- toast helper ---------- */
var toastEl = document.getElementById("toast");
var toastTimer = null;
function toast(msg) {
if (!toastEl) return;
toastEl.textContent = msg;
toastEl.classList.add("show");
clearTimeout(toastTimer);
toastTimer = setTimeout(function () {
toastEl.classList.remove("show");
}, 2400);
}
/* ---------- featured datasets data ---------- */
var DATASETS = [
{
cat: "Climate",
title: "Global Sea Surface Temperature, daily (1982–2026)",
doi: "10.4521/nodi.sst.v7",
fmt: "NetCDF",
size: "412 GB",
lic: "CC0-1.0",
upd: "2026-06-11"
},
{
cat: "Genomics",
title: "Reference Pangenome Assembly — Cohort B (n=1,140)",
doi: "10.4521/nodi.png.0042",
fmt: "FASTA",
size: "2.7 TB",
lic: "ODbL-1.0",
upd: "2026-05-29"
},
{
cat: "Economics",
title: "Consumer Price Index, all urban items (monthly)",
doi: "10.4521/nodi.cpi.m12",
fmt: "CSV",
size: "8.4 MB",
lic: "CC-BY-4.0",
upd: "2026-06-13"
},
{
cat: "Astronomy",
title: "Transiting Exoplanet Photometry — Sector 91",
doi: "10.4521/nodi.tep.s91",
fmt: "Parquet",
size: "61 GB",
lic: "CC0-1.0",
upd: "2026-06-02"
},
{
cat: "Climate",
title: "Arctic Sea-Ice Extent, gridded passive microwave",
doi: "10.4521/nodi.ice.g25",
fmt: "GeoTIFF",
size: "94 GB",
lic: "CC-BY-4.0",
upd: "2026-06-08"
},
{
cat: "Economics",
title: "Regional Labor Market Flows, quarterly panel",
doi: "10.4521/nodi.lmf.q2",
fmt: "JSON",
size: "320 MB",
lic: "CC-BY-4.0",
upd: "2026-04-30"
}
];
var dbody = document.getElementById("dbody");
var tableFoot = document.getElementById("tableFoot");
function rowHTML(d) {
return (
'<tr data-cat="' + d.cat + '">' +
'<td><div class="ds-name">' +
'<span class="ds-title"><span class="cat-tag ' + d.cat + '">' + d.cat + "</span>" + escapeHtml(d.title) + "</span>" +
'<span class="ds-doi">doi:' + d.doi + "</span>" +
"</div></td>" +
'<td><span class="fmt-badge">' + d.fmt + "</span></td>" +
'<td class="num">' + d.size + "</td>" +
'<td><span class="lic">' + d.lic + "</span></td>" +
'<td><span class="upd">' + d.upd + "</span></td>" +
'<td class="ar"><button class="dl-btn" data-title="' + escapeAttr(d.title) + '">' +
'<svg viewBox="0 0 24 24" width="14" height="14"><path d="M12 3v12"/><path d="M7 11l5 5 5-5"/><path d="M5 21h14"/></svg>' +
"Download</button></td>" +
"</tr>"
);
}
function escapeHtml(s) {
return String(s).replace(/[&<>]/g, function (c) {
return { "&": "&", "<": "<", ">": ">" }[c];
});
}
function escapeAttr(s) {
return escapeHtml(s).replace(/"/g, """);
}
var currentFilter = "all";
function renderTable() {
var rows = DATASETS.filter(function (d) {
return currentFilter === "all" || d.cat === currentFilter;
});
dbody.innerHTML = rows.map(rowHTML).join("");
var label =
currentFilter === "all"
? "Showing " + rows.length + " of 4,217 datasets."
: "Showing " + rows.length + " " + currentFilter + " dataset" + (rows.length === 1 ? "" : "s") + " of 4,217 total.";
tableFoot.textContent = label;
}
renderTable();
/* download (event delegation) */
dbody.addEventListener("click", function (e) {
var btn = e.target.closest(".dl-btn");
if (!btn) return;
toast("Preparing download · " + btn.getAttribute("data-title"));
});
/* filter buttons */
var fbtns = document.querySelectorAll(".fbtn");
fbtns.forEach(function (b) {
b.addEventListener("click", function () {
fbtns.forEach(function (x) { x.classList.remove("active"); });
b.classList.add("active");
currentFilter = b.getAttribute("data-filter");
renderTable();
});
});
/* ---------- search ---------- */
var form = document.getElementById("searchForm");
var input = document.getElementById("searchInput");
form.addEventListener("submit", function (e) {
e.preventDefault();
var q = input.value.trim();
if (!q) { toast("Enter a keyword, agency, DOI, or format"); input.focus(); return; }
toast("Searching catalog for “" + q + "” …");
});
document.querySelectorAll(".chip").forEach(function (chip) {
chip.addEventListener("click", function () {
input.value = chip.getAttribute("data-q");
input.focus();
toast("Searching catalog for “" + input.value + "” …");
});
});
/* ---------- category tiles ---------- */
document.querySelectorAll(".tile").forEach(function (tile) {
tile.addEventListener("click", function () {
var cat = tile.getAttribute("data-cat");
var match = document.querySelector('.fbtn[data-filter="' + cat + '"]');
if (match) match.click();
document.getElementById("featured").scrollIntoView({ behavior: "smooth", block: "start" });
toast("Filtered featured datasets to " + cat);
});
});
/* ---------- API snippet tabs ---------- */
var SNIPPETS = {
curl:
'<span class="tok-com"># Fetch the latest CPI release as JSON</span>\n' +
'<span class="tok-cmd">curl</span> <span class="tok-flag">-sH</span> <span class="tok-str">"Accept: application/json"</span> \\\n' +
' <span class="tok-url">https://api.opendata.gov/v3/datasets/nodi.cpi.m12/data</span> \\\n' +
' <span class="tok-flag">--compressed</span> <span class="tok-flag">-o</span> <span class="tok-str">cpi.json</span>',
python:
'<span class="tok-kw">import</span> requests\n\n' +
"r = requests.get(\n" +
' <span class="tok-str">"https://api.opendata.gov/v3/datasets/nodi.cpi.m12/data"</span>,\n' +
' headers={<span class="tok-str">"Accept"</span>: <span class="tok-str">"application/json"</span>},\n' +
")\n" +
"data = r.json()\n" +
'<span class="tok-cmd">print</span>(data[<span class="tok-str">"records"</span>][<span class="tok-str">0</span>])',
js:
'<span class="tok-kw">const</span> res = <span class="tok-kw">await</span> <span class="tok-cmd">fetch</span>(\n' +
' <span class="tok-str">"https://api.opendata.gov/v3/datasets/nodi.cpi.m12/data"</span>,\n' +
' { headers: { <span class="tok-str">"Accept"</span>: <span class="tok-str">"application/json"</span> } }\n' +
");\n" +
'<span class="tok-kw">const</span> data = <span class="tok-kw">await</span> res.json();\n' +
"console.<span class=\"tok-cmd\">log</span>(data.records[<span class=\"tok-str\">0</span>]);"
};
var PLAIN = {
curl:
'# Fetch the latest CPI release as JSON\n' +
'curl -sH "Accept: application/json" \\\n' +
" https://api.opendata.gov/v3/datasets/nodi.cpi.m12/data \\\n" +
" --compressed -o cpi.json",
python:
"import requests\n\n" +
"r = requests.get(\n" +
' "https://api.opendata.gov/v3/datasets/nodi.cpi.m12/data",\n' +
' headers={"Accept": "application/json"},\n' +
")\n" +
"data = r.json()\n" +
'print(data["records"][0])',
js:
'const res = await fetch(\n' +
' "https://api.opendata.gov/v3/datasets/nodi.cpi.m12/data",\n' +
' { headers: { "Accept": "application/json" } }\n' +
");\n" +
"const data = await res.json();\n" +
"console.log(data.records[0]);"
};
var codeBlock = document.getElementById("codeBlock");
var currentLang = "curl";
function setLang(lang) {
currentLang = lang;
codeBlock.innerHTML = SNIPPETS[lang];
}
setLang("curl");
document.querySelectorAll(".atab").forEach(function (tab) {
tab.addEventListener("click", function () {
document.querySelectorAll(".atab").forEach(function (t) {
t.classList.remove("active");
t.setAttribute("aria-selected", "false");
});
tab.classList.add("active");
tab.setAttribute("aria-selected", "true");
setLang(tab.getAttribute("data-lang"));
});
});
/* copy snippet */
var copyBtn = document.getElementById("copyBtn");
copyBtn.addEventListener("click", function () {
var text = PLAIN[currentLang];
var done = function () {
copyBtn.classList.add("done");
var span = copyBtn.querySelector("span");
var prev = span.textContent;
span.textContent = "Copied";
toast("Snippet copied to clipboard");
setTimeout(function () {
copyBtn.classList.remove("done");
span.textContent = prev;
}, 1600);
};
if (navigator.clipboard && navigator.clipboard.writeText) {
navigator.clipboard.writeText(text).then(done, fallbackCopy);
} else {
fallbackCopy();
}
function fallbackCopy() {
try {
var ta = document.createElement("textarea");
ta.value = text;
ta.style.position = "fixed";
ta.style.opacity = "0";
document.body.appendChild(ta);
ta.select();
document.execCommand("copy");
document.body.removeChild(ta);
done();
} catch (err) {
toast("Copy failed — select manually");
}
}
});
/* ---------- sign in ---------- */
document.getElementById("signin").addEventListener("click", function () {
toast("Sign-in is disabled in this demo");
});
/* ---------- animated counters ---------- */
function formatNum(n, fmt) {
if (fmt === "dec") return n.toFixed(1);
return Math.round(n).toLocaleString("en-US");
}
function animateCounter(el) {
var to = parseFloat(el.getAttribute("data-to"));
var fmt = el.getAttribute("data-fmt") || "int";
var suffix = el.getAttribute("data-suffix") || "";
var dur = 1300;
var start = null;
function step(ts) {
if (start === null) start = ts;
var p = Math.min((ts - start) / dur, 1);
var eased = 1 - Math.pow(1 - p, 3);
el.textContent = formatNum(to * eased, fmt) + suffix;
if (p < 1) requestAnimationFrame(step);
else el.textContent = formatNum(to, fmt) + suffix;
}
requestAnimationFrame(step);
}
var statNums = document.querySelectorAll(".stat-num");
if ("IntersectionObserver" in window) {
var io = new IntersectionObserver(
function (entries) {
entries.forEach(function (entry) {
if (entry.isIntersecting) {
animateCounter(entry.target);
io.unobserve(entry.target);
}
});
},
{ threshold: 0.4 }
);
statNums.forEach(function (el) { io.observe(el); });
} else {
statNums.forEach(animateCounter);
}
})();<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>OpenData.gov — National Open Data Portal</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&family=Source+Serif+4:opsz,wght@8..60,400;8..60,600;8..60,700&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="style.css" />
</head>
<body>
<a class="skip" href="#main">Skip to content</a>
<header class="topbar">
<div class="wrap topbar-in">
<a class="brand" href="#" aria-label="OpenData.gov home">
<svg class="brand-mark" viewBox="0 0 24 24" width="26" height="26" aria-hidden="true">
<rect x="2" y="2" width="9" height="9" rx="1.5"/>
<rect x="13" y="2" width="9" height="9" rx="1.5"/>
<rect x="2" y="13" width="9" height="9" rx="1.5"/>
<rect x="13" y="13" width="9" height="9" rx="1.5"/>
</svg>
<span class="brand-txt">OpenData<span class="brand-dot">.gov</span></span>
</a>
<nav class="topnav" aria-label="Primary">
<a href="#catalog">Catalog</a>
<a href="#featured">Datasets</a>
<a href="#api">Developers</a>
<a href="#stats">About</a>
</nav>
<div class="topbar-actions">
<span class="status-pill" title="All systems operational"><span class="dot"></span>API operational</span>
<button class="btn btn-ghost" id="signin">Sign in</button>
</div>
</div>
</header>
<main id="main">
<!-- HERO -->
<section class="hero">
<div class="wrap hero-in">
<p class="kicker">National Open Data Initiative · v3.2</p>
<h1>Search <span class="count" id="heroCount">4,217</span> open datasets</h1>
<p class="lede">Public, machine-readable data from federal agencies and research consortia. Free to download, redistribute, and build on — no registration required.</p>
<form class="search" id="searchForm" role="search" aria-label="Search datasets">
<svg class="search-ico" viewBox="0 0 24 24" width="20" height="20" aria-hidden="true"><circle cx="11" cy="11" r="7"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
<input id="searchInput" type="search" autocomplete="off"
placeholder="Search by keyword, agency, DOI, or format…" aria-label="Search query" />
<button class="btn btn-accent" type="submit">Search</button>
</form>
<div class="chips" aria-label="Example queries">
<span class="chips-label">Try:</span>
<button class="chip" data-q="sea surface temperature">sea surface temperature</button>
<button class="chip" data-q="genome assembly GRCh38">genome assembly GRCh38</button>
<button class="chip" data-q="CPI inflation monthly">CPI inflation monthly</button>
<button class="chip" data-q="exoplanet transit photometry">exoplanet transit photometry</button>
</div>
</div>
</section>
<!-- CATEGORIES -->
<section class="section" id="catalog" aria-labelledby="cat-h">
<div class="wrap">
<div class="sec-head">
<h2 id="cat-h">Browse by category</h2>
<a class="link-more" href="#">View all 18 categories →</a>
</div>
<div class="cat-grid" id="catGrid">
<button class="tile" data-cat="Climate">
<div class="tile-ico clim" aria-hidden="true">
<svg viewBox="0 0 24 24" width="22" height="22"><path d="M3 15a4 4 0 0 1 4-4 5 5 0 0 1 9.6-1.5A3.5 3.5 0 1 1 18 18H7a4 4 0 0 1-4-3z"/></svg>
</div>
<div class="tile-body">
<span class="tile-name">Climate & Weather</span>
<span class="tile-meta"><b data-count="1284">1,284</b> datasets · 3.1 PB</span>
</div>
</button>
<button class="tile" data-cat="Genomics">
<div class="tile-ico geno" aria-hidden="true">
<svg viewBox="0 0 24 24" width="22" height="22"><path d="M5 4c8 4 6 12 14 16M19 4C11 8 13 16 5 20"/><line x1="8" y1="7" x2="14" y2="7"/><line x1="9" y1="12" x2="15" y2="12"/><line x1="10" y1="17" x2="16" y2="17"/></svg>
</div>
<div class="tile-body">
<span class="tile-name">Genomics</span>
<span class="tile-meta"><b data-count="932">932</b> datasets · 11.4 PB</span>
</div>
</button>
<button class="tile" data-cat="Economics">
<div class="tile-ico econ" aria-hidden="true">
<svg viewBox="0 0 24 24" width="22" height="22"><polyline points="3 17 9 11 13 15 21 6"/><polyline points="15 6 21 6 21 12"/></svg>
</div>
<div class="tile-body">
<span class="tile-name">Economics</span>
<span class="tile-meta"><b data-count="1106">1,106</b> datasets · 84 TB</span>
</div>
</button>
<button class="tile" data-cat="Astronomy">
<div class="tile-ico astro" aria-hidden="true">
<svg viewBox="0 0 24 24" width="22" height="22"><circle cx="12" cy="12" r="3.2"/><ellipse cx="12" cy="12" rx="10" ry="4.2" transform="rotate(28 12 12)"/></svg>
</div>
<div class="tile-body">
<span class="tile-name">Astronomy</span>
<span class="tile-meta"><b data-count="895">895</b> datasets · 27 PB</span>
</div>
</button>
</div>
</div>
</section>
<!-- FEATURED TABLE -->
<section class="section alt" id="featured" aria-labelledby="feat-h">
<div class="wrap">
<div class="sec-head">
<h2 id="feat-h">Featured datasets</h2>
<div class="filter" role="group" aria-label="Filter featured datasets by category">
<button class="fbtn active" data-filter="all">All</button>
<button class="fbtn" data-filter="Climate">Climate</button>
<button class="fbtn" data-filter="Genomics">Genomics</button>
<button class="fbtn" data-filter="Economics">Economics</button>
<button class="fbtn" data-filter="Astronomy">Astronomy</button>
</div>
</div>
<div class="table-scroll">
<table class="dtable" id="dtable">
<thead>
<tr>
<th scope="col">Dataset</th>
<th scope="col">Format</th>
<th scope="col" class="num">Size</th>
<th scope="col">License</th>
<th scope="col">Updated</th>
<th scope="col" class="ar">Access</th>
</tr>
</thead>
<tbody id="dbody"><!-- rows injected by script.js --></tbody>
</table>
</div>
<p class="table-foot" id="tableFoot">Showing 6 of 4,217 datasets.</p>
</div>
</section>
<!-- API PANEL -->
<section class="section" id="api" aria-labelledby="api-h">
<div class="wrap api-grid">
<div class="api-copy">
<p class="kicker">Programmatic access</p>
<h2 id="api-h">Build with the Data API</h2>
<p class="lede">Every dataset is reachable over a versioned REST endpoint returning JSON, CSV, or Parquet. Anonymous access is rate-limited to 60 req/min; issue a free token for 5,000 req/min.</p>
<ul class="api-feats">
<li><span class="fdot ok"></span> OpenAPI 3.1 schema & SDKs (Python, R, JS)</li>
<li><span class="fdot ok"></span> Stable DOIs & content-addressed snapshots</li>
<li><span class="fdot ok"></span> CORS-enabled, gzip + Brotli, HTTP range requests</li>
</ul>
</div>
<div class="api-panel" aria-label="API endpoint example">
<div class="api-tabs" role="tablist" aria-label="Snippet language">
<button class="atab active" data-lang="curl" role="tab" aria-selected="true">cURL</button>
<button class="atab" data-lang="python" role="tab" aria-selected="false">Python</button>
<button class="atab" data-lang="js" role="tab" aria-selected="false">JavaScript</button>
</div>
<div class="api-code">
<div class="api-code-top">
<span class="api-endpoint">GET /v3/datasets/{id}/data</span>
<button class="copy-btn" id="copyBtn" aria-label="Copy snippet to clipboard">
<svg viewBox="0 0 24 24" width="15" height="15" aria-hidden="true"><rect x="9" y="9" width="11" height="11" rx="2"/><path d="M5 15V5a2 2 0 0 1 2-2h10"/></svg>
<span>Copy</span>
</button>
</div>
<pre class="code"><code id="codeBlock"></code></pre>
</div>
<div class="api-resp">
<span class="resp-status">200 OK</span>
<span class="resp-meta">application/json · 18.4 KB · 42 ms</span>
</div>
</div>
</div>
</section>
<!-- STATS -->
<section class="section alt" id="stats" aria-labelledby="stats-h">
<div class="wrap">
<h2 id="stats-h" class="sr-only">Portal usage statistics</h2>
<div class="stat-grid" id="statGrid">
<div class="stat"><span class="stat-num" data-to="4217" data-fmt="int">0</span><span class="stat-lbl">Open datasets</span></div>
<div class="stat"><span class="stat-num" data-to="61.8" data-fmt="dec" data-suffix=" PB">0</span><span class="stat-lbl">Data served (2026)</span></div>
<div class="stat"><span class="stat-num" data-to="312000" data-fmt="int" data-suffix="+">0</span><span class="stat-lbl">API calls / day</span></div>
<div class="stat"><span class="stat-num" data-to="143" data-fmt="int">0</span><span class="stat-lbl">Contributing agencies</span></div>
</div>
</div>
</section>
</main>
<footer class="footer">
<div class="wrap footer-in">
<div class="foot-brand">
<a class="brand" href="#">
<svg class="brand-mark" viewBox="0 0 24 24" width="22" height="22" aria-hidden="true">
<rect x="2" y="2" width="9" height="9" rx="1.5"/><rect x="13" y="2" width="9" height="9" rx="1.5"/>
<rect x="2" y="13" width="9" height="9" rx="1.5"/><rect x="13" y="13" width="9" height="9" rx="1.5"/>
</svg>
<span class="brand-txt">OpenData<span class="brand-dot">.gov</span></span>
</a>
<p class="foot-note">Public-domain data, released under open licenses. Built for researchers, journalists, and developers.</p>
</div>
<div class="foot-cols">
<div class="foot-col">
<h3>Developers</h3>
<a href="#">API reference</a><a href="#">OpenAPI schema</a><a href="#">Status & SLA</a><a href="#">Changelog</a>
</div>
<div class="foot-col">
<h3>Data</h3>
<a href="#">Catalog</a><a href="#">Bulk downloads</a><a href="#">DOIs & citation</a><a href="#">Licenses</a>
</div>
<div class="foot-col">
<h3>Portal</h3>
<a href="#">Governance</a><a href="#">Privacy</a><a href="#">Accessibility</a><a href="#">Contact</a>
</div>
</div>
</div>
<div class="wrap foot-bottom">
<span>© 2026 National Open Data Initiative · Illustrative demo</span>
<code class="foot-base">base: api.opendata.gov/v3</code>
</div>
</footer>
<div class="toast" id="toast" role="status" aria-live="polite"></div>
<script src="script.js"></script>
</body>
</html>Open Data / Dataset Portal Landing
A utilitarian homepage for a fictional national open-data portal, built in the slate-and-green palette of a government technical site. The hero leads with a single job — search across 4,217 open datasets — backed by a focus-ring search field and mono-styled example-query chips that populate the input on click. Below it, four category tiles (Climate, Genomics, Economics, Astronomy) surface dataset counts and storage volume, and clicking one filters the featured table and scrolls to it.
The featured-datasets section is a dense, scroll-on-narrow table with format badges, byte sizes,
SPDX-style license codes, ISO update dates, and per-row download buttons; a filter bar toggles
between categories and updates a live result count. A developer access panel presents the REST
endpoint with tabbed cURL, Python, and JavaScript snippets in a dark mono block, each with
syntax-style coloring and a copy-to-clipboard button (with a graceful execCommand fallback).
Usage-stat counters animate from zero with an ease-out curve when scrolled into view via
IntersectionObserver, a small toast() helper acknowledges every interaction, and the page is
fully keyboard-operable with semantic landmarks, visible focus, and a responsive layout that
collapses cleanly down to ~360px. All logic is dependency-free vanilla JS.
Illustrative UI only — fictional authors, data, and figures; not real scientific results.