GeoJSON (RFC 7946) stores each feature's coordinates in full, so shared borders appear twice. TopoJSON 4,906 stores them once as arcs of quantized, delta-encoded integers, and is far smaller. topojson-client (3.1.0) converts back: topojson.feature(topo, object) gives features to fill, and topojson.mesh(topo, object, (a, b) => a !== b) the interior borders as one line.
Measured on jsDelivr 15,886 : world-atlas@2.0.2/countries-110m.json (177 countries, 595 arcs) is 108 KB, land-110m.json 55 KB, countries-50m.json 756 KB; us-atlas@3.0.1/states-10m.json is 115 KB and counties-10m.json 842 KB.
Both derive from Natural Earth (public domain) and are ISC licensed. Countries carry ISO 3166-1 numeric ids as strings ("036" is Australia), which BookNest's sample regions reuse; jsDelivr allows cross-origin fetches.
<!doctype html>
<style>
body { margin: 0; padding: 8px; background: #fafaf7; font: 12px system-ui, sans-serif; color: #263238; }
svg { width: 100%; max-width: 600px; display: block; background: #eef4f7; }
</style>
<script src="https://cdn.jsdelivr.net/npm/d3@7.9.0/dist/d3.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/topojson-client@3.1.0"></script>
<p><label><input type="checkbox" id="mesh" checked> topojson.mesh(): interior borders as one path</label></p>
<svg viewBox="0 0 600 330" font-size="10"></svg>
<p id="out"></p>
<script>
// 25 European countries, simplified from world-atlas countries-110m.json (Natural Earth, public domain).
// Borders are stored once as quantized, delta-encoded arcs shared by both neighbours.
const topo = {"type":"Topology","transform":{"scale":[0.03600036000360004,0.016925586033320103],"translate":[-180,-85.60903777459771]},"objects":{"countries":{"type":"GeometryCollection","geometries":[{"type":"Polygon","id":"578","properties":{"name":"Norway"},"arcs":[[-1,1,2,3]]},{"type":"MultiPolygon","id":"250","properties":{"name":"France"},"arcs":[[[4,5,6,7,8,9,10,11]],[[12]]]},{"type":"Polygon","id":"752","properties":{"name":"Sweden"},"arcs":[[-3,13,14]]},{"type":"Polygon","id":"616","properties":{"name":"Poland"},"arcs":[[-16,-17,17,18,19,20,-22,22]]},{"type":"Polygon","id":"040","properties":{"name":"Austria"},"arcs":[[23,24,25,26,27,28,29]]},{"type":"Polygon","id":"348","properties":{"name":"Hungary"},"arcs":[[-31,31,32,33,34,-24,35]]},{"type":"Polygon","id":"642","properties":{"name":"Romania"},"arcs":[[-37,37,38,39,-32,-41,-42]]},{"type":"Polygon","id":"276","properties":{"name":"Germany"},"arcs":[[-20,42,-28,43,-5,44,45,46,47,48,49]]},{"type":"Polygon","id":"100","properties":{"name":"Bulgaria"},"arcs":[[-39,50,51,52,53,54]]},{"type":"MultiPolygon","id":"300","properties":{"name":"Greece"},"arcs":[[[55]],[[-53,56,57,58,59]]]},{"type":"Polygon","id":"191","properties":{"name":"Croatia"},"arcs":[[-34,60,61,62,63,64]]},{"type":"Polygon","id":"756","properties":{"name":"Switzerland"},"arcs":[[-27,65,-6,-44]]},{"type":"Polygon","id":"442","properties":{"name":"Luxembourg"},"arcs":[[-45,-12,66]]},{"type":"Polygon","id":"056","properties":{"name":"Belgium"},"arcs":[[-46,-67,-11,67,68]]},{"type":"Polygon","id":"528","properties":{"name":"Netherlands"},"arcs":[[-47,-69,69]]},{"type":"Polygon","id":"620","properties":{"name":"Portugal"},"arcs":[[70,71]]},{"type":"Polygon","id":"724","properties":{"name":"Spain"},"arcs":[[-71,72,-9,73]]},{"type":"Polygon","id":"372","properties":{"name":"Ireland"},"arcs":[[74,75]]},{"type":"MultiPolygon","id":"380","properties":{"name":"Italy"},"arcs":[[[-26,76,77,-7,-66]],[[78]],[[79]]]},{"type":"MultiPolygon","id":"208","properties":{"name":"Denmark"},"arcs":[[[-49,80]],[[81]]]},{"type":"MultiPolygon","id":"826","properties":{"name":"United Kingdom"},"arcs":[[[-76,82]],[[83]]]},{"type":"Polygon","id":"705","properties":{"name":"Slovenia"},"arcs":[[-25,-35,-65,84,-77]]},{"type":"Polygon","id":"246","properties":{"name":"Finland"},"arcs":[[-86,86,-14,-2]]},{"type":"Polygon","id":"703","properties":{"name":"Slovakia"},"arcs":[[-88,-36,-30,88,-18]]},{"type":"Polygon","id":"203","properties":{"name":"Czechia"},"arcs":[[-19,-89,-29,-43]]}]}},"arcs":[[[5794,9139],[70,29]],[[5794,9139],[12,41],[-36,23],[-83,-89],[-114,27]],[[5573,9141],[-21,-41],[-52,9],[-34,-33],[-89,-234],[-28,1],[-7,-233],[-36,-75]],[[5306,8535],[-18,37],[-55,-69],[-37,-14],[-39,31],[-18,199],[153,149],[118,196],[123,119],[107,23],[42,49],[100,9],[87,-43],[-36,-16],[31,-37]],[[5172,7980],[53,-26],[-18,-82]],[[5207,7872],[-39,-53],[22,-44]],[[5190,7775],[17,-135]],[[5207,7640],[-26,-34],[-95,-3],[-3,-36]],[[5083,7567],[-74,7],[-62,50]],[[4947,7624],[20,153],[-95,157],[83,-2],[-9,67],[27,-25],[97,106]],[[5070,8080],[88,-96]],[[5158,7984],[14,-4]],[[5243,7577],[18,22],[-5,-96],[-13,74]],[[5573,9141],[81,-69],[10,-114]],[[5664,8958],[-48,-17],[-22,-77],[-98,-99],[-20,-83],[46,-74],[-55,-81],[-26,-154],[-34,5],[-15,-46],[-32,-3],[-54,206]],[[5654,8105],[-2,138]],[[5627,7958],[38,79],[-11,68]],[[5627,7958],[-103,24]],[[5524,7982],[-107,96]],[[5417,8078],[-25,156]],[[5392,8234],[98,65],[56,-25]],[[5631,8268],[-85,6]],[[5631,8268],[21,-25]],[[5472,7901],[-22,-75]],[[5450,7826],[-66,-20]],[[5384,7806],[-46,36],[-48,-13]],[[5290,7829],[-23,37]],[[5267,7866],[92,-3],[19,83]],[[5378,7946],[93,-17]],[[5471,7929],[1,-28]],[[5631,7887],[-18,32]],[[5631,7887],[-69,-104]],[[5562,7783],[-39,-13]],[[5523,7770],[-63,36]],[[5460,7806],[-10,20]],[[5472,7901],[24,-21],[82,51],[35,-12]],[[5822,7734],[-38,12]],[[5822,7734],[-29,-94]],[[5793,7640],[-36,28],[-47,-29],[-73,8],[-8,25]],[[5629,7672],[-67,111]],[[5739,7907],[-108,-20]],[[5784,7746],[-45,161]],[[5417,8078],[-77,-50],[38,-82]],[[5267,7866],[-60,6]],[[5172,7980],[-4,40]],[[5168,8020],[3,40]],[[5171,8060],[21,158]],[[5192,8218],[52,32],[-7,55]],[[5237,8305],[39,2]],[[5276,8307],[28,-58],[44,27],[44,-42]],[[5793,7640],[-15,-100]],[[5778,7540],[-53,-11]],[[5725,7529],[0,-29],[-87,0]],[[5638,7500],[-16,58]],[[5622,7558],[7,114]],[[5730,7144],[-43,-23],[-34,21],[5,26],[72,-24]],[[5725,7529],[-1,-59]],[[5724,7470],[-65,-8],[5,-43],[-35,17],[38,-120],[-34,-54],[10,-52],[-41,25],[-42,164]],[[5560,7399],[24,72]],[[5584,7471],[54,29]],[[5523,7770],[5,-62]],[[5528,7708],[-85,23],[-6,-25],[79,-128]],[[5516,7578],[-4,-10]],[[5512,7568],[-131,178]],[[5381,7746],[45,-3],[34,63]],[[5290,7829],[-41,-51],[-59,-3]],[[5158,7984],[10,36]],[[5070,8080],[22,12]],[[5092,8092],[46,7],[33,-39]],[[5092,8092],[39,103],[61,23]],[[4749,7532],[21,24],[53,-53],[-30,-253]],[[4793,7250],[-40,-14],[-18,111],[14,185]],[[4749,7532],[-10,68],[39,43],[169,-19]],[[5083,7567],[-25,-73],[-35,-13],[-20,-134],[-63,-122],[-61,0],[-28,-43],[-58,68]],[[4828,8241],[-17,-95],[-88,-26],[8,121],[59,74]],[[4790,8315],[0,-63],[38,-11]],[[5384,7806],[3,-54]],[[5387,7752],[-45,-13],[8,-76],[163,-232],[-5,-21],[-39,37],[-22,-145],[-19,122],[-117,136],[-28,93],[-36,26],[-40,-39]],[[5410,7312],[21,5],[-12,-95],[-74,58],[4,31],[61,1]],[[5242,7474],[14,19],[16,-42],[-27,-94],[-3,117]],[[5237,8305],[-8,109],[65,55],[-18,-162]],[[5344,8373],[-8,-77],[-33,58],[41,19]],[[4790,8315],[53,-34],[-15,-40]],[[4914,8213],[-85,200],[32,109],[56,0],[-30,-64],[59,8],[-33,-101],[29,-4],[71,-176],[34,-11],[-32,-117],[-97,-4],[-64,-43],[51,86],[-51,34],[29,18],[-10,71],[41,-6]],[[5381,7746],[6,6]],[[5780,8633],[95,139],[-41,41],[5,133],[-32,67],[26,45],[-43,39],[4,42]],[[5780,8633],[-145,-39],[-43,51],[6,146],[107,114],[-41,53]],[[5613,7919],[14,39]],[[5471,7929],[53,53]]]};
const countries = topojson.feature(topo, topo.objects.countries); // GeoJSON features to fill
const borders = topojson.mesh(topo, topo.objects.countries, (a, b) => a !== b); // shared borders only
const projection = d3.geoConicEqualArea().parallels([43, 62]).rotate([-10, 0])
.fitExtent([[10, 10], [590, 320]], countries);
const path = d3.geoPath(projection), svg = d3.select('svg');
svg.append('path').datum(d3.geoGraticule10()).attr('d', path).attr('fill', 'none').attr('stroke', '#d5e1e8');
svg.append('g').selectAll('path').data(countries.features).join('path').attr('d', path)
.attr('fill', (d, i) => d3.schemeTableau10[i % 10]).attr('fill-opacity', 0.35).attr('stroke', 'none')
.append('title').text(d => `${d.properties.name} (id "${d.id}")`);
const mesh = svg.append('path').datum(borders).attr('d', path)
.attr('fill', 'none').attr('stroke', '#b5452f').attr('stroke-width', 1.2);
svg.append('g').selectAll('text').data(countries.features.filter(f => path.area(f) > 1500)).join('text')
.attr('transform', d => `translate(${path.centroid(d)})`).attr('text-anchor', 'middle').text(d => d.id);
d3.select('#mesh').on('change', e => mesh.attr('display', e.target.checked ? null : 'none'));
const kb = s => (s.length / 1024).toFixed(1) + ' KB';
d3.select('#out').text(`TopoJSON ${kb(JSON.stringify(topo))} (${topo.arcs.length} arcs) → ` +
`GeoJSON ${kb(JSON.stringify(countries))} (${countries.features.length} features); ` +
`numbers are ISO 3166-1 ids, such as "826" for the United Kingdom.`);
</script>