@anaybucket/travel-atlas
v0.1.2
Published
A React travel atlas for visited countries, planned places, and trip routes.
Readme
Travel Atlas
A React + TypeScript atlas component for visited countries, want-to-visit countries, city markers, and trip routes.
This package is intentionally data-first: your app owns the travel content, and the atlas renders it.
Features
- Bundled Natural Earth world map via
world-atlas. - ISO alpha-3 country authoring with internal numeric map-id lookup.
- Zoomable/pannable SVG atlas up to
1000%. - Optional orthographic globe renderer with drag rotation and projected routes.
- Clickable country and city layers with nested label toggles.
- City visibility is a superset of country visibility: turning cities on always shows countries too.
- Country and city clicks select the country and refocus the map viewport.
- Visited, lived, and want-to-visit country states.
- Completed and planned trip routes.
- Completed and planned trip layer toggles.
- One-trip or all-trips route display modes.
- Inverse-scaled markers that stay crisp while zooming.
- Pure TypeScript helpers for route generation and data validation.
- Country lookup helpers for name, alpha-2, alpha-3, and numeric ids.
- Optional city gazetteer lookup through
@anaybucket/travel-atlas/gazetteer. - Optional Bun SQLite adapter through
@anaybucket/travel-atlas/db.
Install
bun add @anaybucket/travel-atlasUsage
import { TravelAtlas, type TravelCountry, type TravelTrip } from '@anaybucket/travel-atlas'
import '@anaybucket/travel-atlas/style.css'
const countries = [
{
code: 'JPN',
name: 'Japan',
coordinates: [138.2529, 36.2048],
status: 'visited',
cities: [
{ id: 'tokyo', name: 'Tokyo', coordinates: [139.6917, 35.6895] },
{ id: 'kyoto', name: 'Kyoto', coordinates: [135.7681, 35.0116] },
],
},
] satisfies TravelCountry[]
const trips = [
{
id: 'japan-2024',
name: 'Japan 2024',
status: 'completed',
stops: [
{ countryCode: 'JPN', cityId: 'tokyo' },
{ countryCode: 'JPN', cityId: 'kyoto' },
],
},
] satisfies TravelTrip[]
export function App() {
return <TravelAtlas countries={countries} trips={trips} enableZoom />
}Coordinates are always [longitude, latitude].
Trip routes default to showing one selected trip at a time. Set
defaultTripDisplayMode="all" when you want the atlas to initially show every
visible trip route while the selected trip still owns the detail panel and stop
markers.
To render the same data as a simulated 3D globe, switch the renderer:
export function App() {
return <TravelAtlas countries={countries} trips={trips} renderer="globe" />
}The globe can also be imported directly from the optional subpath:
import { TravelGlobe } from '@anaybucket/travel-atlas/globe'Place Helpers
Countries can be resolved from a name or code:
import { createTravelCountry, createTravelCity } from '@anaybucket/travel-atlas'
const japan = createTravelCountry({
country: 'Japan',
status: 'visited',
cities: [
createTravelCity({
name: 'Osaka',
coordinates: [135.5023, 34.6937],
}),
],
})City coordinates still need to come from your data or a geocoder, but the helper keeps ids and country metadata consistent.
Optional City Gazetteer
For admin scripts, install the optional city dataset:
bun add -D all-the-citiesThen use the package subpath:
import {
createCityInputFromGazetteer,
findCity,
} from '@anaybucket/travel-atlas/gazetteer'
import { upsertCity } from '@anaybucket/travel-atlas/db'
const tokyo = await findCity('Tokyo', { country: 'Japan' })
if (tokyo) {
upsertCity(db, createCityInputFromGazetteer(tokyo))
}This subpath is meant for Bun scripts, build steps, or admin tooling. It should not be imported into the browser-rendered React app.
Optional SQLite Adapter
The React package works with plain data. If you want a tiny local database as the source of truth, import the optional Bun-only adapter:
import {
exportTravelAtlasData,
openTravelAtlasDatabase,
seedCountryCatalog,
} from '@anaybucket/travel-atlas/db'
const db = openTravelAtlasDatabase('travel-atlas.sqlite')
seedCountryCatalog(db)
const { countries, trips } = exportTravelAtlasData(db)Use the ./db entry in a Bun script, server route, or static build step, then
pass the exported countries and trips into TravelAtlas. The browser entry
point does not import bun:sqlite.
The adapter creates only the default atlas tables for countries, city nodes,
want-to-visit/visited/lived state, trips, and ordered trip stops. Custom website
data can live in your own SQLite tables beside those defaults and join through
country_code, (country_code, city_id), or trip_id.
Scripts
bun install
bun test
bun run typecheck
bun run build
bun run devThe demo app runs at the Vite URL printed by bun run dev.
