<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/you-start-with-cities-for-one-country-then-one-day-you-need-the-whole-world--jyp9hpcok" -->

---
title: You start with cities for one country... then one day...
description: A developer open-sourced a self-hostable city search and address autocomplete API after repeatedly rebuilding the same component across projects. Built with...
canonical: https://daily.dev/posts/you-start-with-cities-for-one-country-then-one-day-you-need-the-whole-world--jyp9hpcok
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: You start with cities for one country... then one day you need the whole world. | daily.dev
og:description: A developer open-sourced a self-hostable city search and address autocomplete API after repeatedly rebuilding the same component across projects. Built with...
og:url: https://daily.dev/posts/you-start-with-cities-for-one-country-then-one-day-you-need-the-whole-world--jyp9hpcok
og:image: https://api.daily.dev/og/posts/jyP9Hpcok.png
og:image:alt: You start with cities for one country... then one day you need the whole world.
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# You start with cities for one country... then one day you need the whole world.

**[Thomas Laure](https://daily.dev/sources/3ks1x5x5e)** · [@thomas_l](https://daily.dev/thomas_l) · 2 min read · 2 upvotes · 0 comments

## Summary

A developer open-sourced a self-hostable city search and address autocomplete API after repeatedly rebuilding the same component across projects. Built with Symfony, API Platform, and PostgreSQL, it supports international cities, ISO country codes, and multiple data providers including OpenStreetMap via Photon. Deployable with Docker or Podman, it uses hexagonal architecture, 100% domain-layer unit test coverage, and Behat for API tests. The author is seeking feedback from developers who have solved similar geolocation data problems in production.

## Content

I've been bitten by this more than once.

On one project, I needed an API for city lookup and address autocomplete.

It usually starts with a simple table containing cities for a single country.

Then requirements evolve:

- support international cities;
- handle ISO country codes;
- import data from different providers.

Or even worse, someone decides users should be able to maintain the city database manually.

So instead of writing the same component again, I cleaned it up and open-sourced it.

Features:

- City search
- Address autocomplete powered by OpenStreetMap (Photon)
- Deployable with Docker or Podman in a few commands
- Designed to be easily extended if another data source needs to be plugged in

Tech stack:

- Symfony / API Platform / PostgreSQL
- Hexagonal Architecture
- 100% unit test coverage on the domain layer
- Behat scenarios used both as executable documentation and API tests

I don't think this project is going to change the world.

But if it helps someone avoid a questionable data model, or rewriting the same component for the tenth time, then it's already worth it.

Repository: [https://github.com/thlaure/world-cities-api](https://github.com/thlaure/world-cities-api)

I'm genuinely interested in feedback, especially from people who have had to solve the same problem in production.

## Similar posts on daily.dev

- [Postcodes for Laravel: GB Postcode Lookup and Geography Data](https://daily.dev/posts/postcodes-for-laravel-gb-postcode-lookup-and-geography-data-qvakwweol) · Laravel News · 3 upvotes · 0 comments
- [Case Study: Scanning for quality: How Yuka fuels healthy choices at global scale with Symfony \(Symfony Blog\)](https://daily.dev/posts/case-study-scanning-for-quality-how-yuka-fuels-healthy-choices-at-global-scale-with-symfony-symfo-ikmeodwjc) · Symfony · 1 upvotes · 1 comments
- [Geocoding with Cloudflare](https://daily.dev/posts/geocoding-with-cloudflare-2tzjuiam5) · Laravel News · 0 upvotes · 0 comments
- [Geocoding natively in Snowflake with Overture Data \(Carto\) for Free\*](https://daily.dev/posts/geocoding-natively-in-snowflake-with-overture-data-carto-for-free--p6eupgoof) · Snowflake Community · 0 upvotes · 0 comments
- [World geography gotchas](https://daily.dev/posts/world-geography-gotchas-4tly7cdnx) · A Java geek · 0 upvotes · 0 comments

---

Tags: [#open-source](https://daily.dev/tags/open-source), [#architecture](https://daily.dev/tags/architecture), [#postgresql](https://daily.dev/tags/postgresql), [#symfony](https://daily.dev/tags/symfony)

[View this post on daily.dev](https://daily.dev/posts/you-start-with-cities-for-one-country-then-one-day-you-need-the-whole-world--jyp9hpcok)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"DiscussionForumPosting","mainEntityOfPage":"https://daily.dev/posts/you-start-with-cities-for-one-country-then-one-day-you-need-the-whole-world--jyp9hpcok","headline":"You start with cities for one country... then one day you need the whole world.","text":"A developer open-sourced a self-hostable city search and address autocomplete API after repeatedly rebuilding the same component across projects. Built with Symfony, API Platform, and PostgreSQL, it supports international cities, ISO country codes, and multiple data providers including OpenStreetMap via Photon. Deployable with Docker or Podman, it uses hexagonal architecture, 100% domain-layer unit test coverage, and Behat for API tests. The author is seeking feedback from developers who have solved similar geolocation data problems in production.","url":"https://daily.dev/posts/you-start-with-cities-for-one-country-then-one-day-you-need-the-whole-world--jyp9hpcok","datePublished":"2026-07-15T07:27:45.397Z","dateModified":"2026-09-13T21:10:24.558Z","author":{"@type":"Person","name":"Thomas Laure","url":"https://daily.dev/thomas_l","image":"https://avatars.githubusercontent.com/u/25416156?v=4","description":"Software Engineer | PHP/Symfony","worksFor":{"@type":"Organization","name":"Enovacom","logo":"https://media.daily.dev/image/upload/s--37NuWhQX--/f_auto/v1745576150/companies/enovacom"},"interactionStatistic":{"@type":"InteractionCounter","interactionType":{"@type":"EndorseAction"},"userInteractionCount":2080}},"interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":2},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"isPartOf":{"@type":"WebPage","url":"https://daily.dev/sources/3ks1x5x5e","name":"Thomas Laure"}}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Thomas Laure","item":"https://daily.dev/sources/3ks1x5x5e"},{"@type":"ListItem","position":3,"name":"You start with cities for one country... then one day you need the whole world."}]}
```

