Job seekers filter by city constantly — "remote", "hybrid in Austin", "on-site in Berlin" — but a plain text input invites typos and inconsistent spellings ("NYC" vs "New York" vs "new york city"), which either under-matches listings or forces you to maintain a manual alias table. A dedicated city autocomplete fixes this at the input, not the query layer: users pick from real, deduplicated cities, so the value stored in your job listing's location field is always a stable ID or canonical name, not free text.
Try typing a US city below — this is the same free, no-key endpoint used on the snippet underneath.
A minimal city filter field — swap the country code for whichever markets your job board serves:
<input id="city-filter" placeholder="Filter by city..." autocomplete="off" />
<div id="city-results"></div>
<script>
const input = document.getElementById('city-filter');
const results = document.getElementById('city-results');
let debounce;
input.addEventListener('input', (e) => {
clearTimeout(debounce);
const prefix = e.target.value.trim().toLowerCase();
if (!prefix) { results.innerHTML = ''; return; }
debounce = setTimeout(async () => {
const res = await fetch(`https://oneshot.geomelon.dev/us/en/${encodeURIComponent(prefix)}`);
const cities = res.ok ? await res.json() : [];
results.innerHTML = cities
.map((c) => `<div data-city-id="${c.id}">${c.name}</div>`)
.join('');
}, 150);
});
</script>For filtering your actual job listings by the selected city (not just autocomplete), use GET /cities/search?name=...&countryCode=... from the main API to resolve the canonical city ID, then store that ID on the listing instead of free text.