Simple systems tend to last because they're easier to maintain, explain, test, and recover.
Complexity can create short-term speed, but simplicity builds long-term trust.
When a system grows, break it into smaller chunks (modules/services) so changes stay local and safer.
Give each chunk a single purpose and clear boundaries, so it can be understood and evolved independently.
(Not "isolated forever" - just intentionally scoped.)
Keeping chunks small and maintainable is one of the most reliable strategies in system design -
not a universal law, but a principle that keeps paying rent.
Every time I touch GIS coordinates, I hit the same trap: sometimes coordinates are written as
latitude then longitude, and sometimes they are longitude then latitude. Both look valid, both are common,
and the mistake often does not throw an error. Instead, the point quietly lands in the wrong country,
or worse, in the ocean.
This post is my quick reference: first the mental model (why the order differs),
then the technique I used in my own project to stop the confusion from spreading.
A picture of the classic bug
When lat and lon get swapped, a real point often ends up "somewhere in the ocean."
(If you are adding an image here, upload it to Blogspot first, then insert it into this section.)
A swapped coordinate pair often becomes a pin in the ocean, with no error messages.
The two worlds that collide
There are two different coordinate traditions that keep clashing:
1) Human geography tradition: (latitude, longitude)
Most people learn latitude and longitude in school as:
Latitude: north or south (up and down)
Longitude: east or west (left and right)
So a location is commonly written as:
(lat, lon)
Example for Kuala Lumpur (approx):
(3.1390, 101.6869)
This feels natural because we say "latitude and longitude" in that order.
2) Mapping and GIS tradition: (x, y) which becomes (longitude, latitude)
Most mapping engines and GIS systems think in Cartesian terms:
X axis is horizontal
Y axis is vertical
When coordinates are mapped into (x, y):
X corresponds to longitude
Y corresponds to latitude
So in GIS engine terms the same point becomes:
(lon, lat)
Same Kuala Lumpur example:
(101.6869, 3.1390)
This is not random. It is the consistent "x first, y second" rule.
The most important practical rule: GeoJSON is strict
If I am dealing with GeoJSON, there is almost no debate:
GeoJSON Point coordinates are always [longitude, latitude]
If I swap them to [lat, lon], the data is still valid JSON, but the point ends up in the wrong place.
That is why this bug can be so annoying.
Databases and spatial functions usually follow x, y too
Many spatial databases and geometry constructors follow:
(x, y) = (lon, lat)
Even if a library accepts different input types, the underlying geometry model is still "x then y."
Why this confusion keeps happening
People say "lat/long" in that order for decades, so apps and UIs follow it.
GIS engines and geometry models prefer "x/y," which becomes lon/lat.
Some libraries try to be helpful and auto-swap depending on context.
Some standards define axis order, but older systems may ignore it, so behavior varies.
The technique that stopped it in my codebase
The conceptual explanation is useful, but it does not prevent bugs.
What actually helped was enforcing one simple rule:
never manually swap coordinate order scattered around the code.
Instead, I introduced a single conversion layer that acts as the boundary between:
Frontend map UI (Leaflet), which naturally works with (lat, lng)
Storage and backend models, which I keep aligned to (lng, lat) / (x, y)
Concept: "Coordinate conversion layer"
In my project I called it CoordinateConversionService, but the important part is not the name.
The idea is: create one dedicated place that converts between formats, and make every other part of the app
call into it. This turns a messy convention problem into a controlled interface.
Typical responsibilities of this conversion layer:
Convert Leaflet coordinates (lat,lng) to GeoJSON coordinates (lng,lat) for saving.
Convert GeoJSON (lng,lat) back to Leaflet (lat,lng) for rendering.
If the backend stores GPS as x,y, keep x=lng and y=lat consistently.
Concept: "Update direction guard" (to avoid feedback loops)
A second practical issue appears in map editors: there are two ways a coordinate can change.
User drags a marker on the map, and the form fields must update.
User edits the coordinate fields, and the marker must move.
If both directions trigger each other, the app can end up in a loop or jittery updates.
The simplest fix is to track the source of the current update.
In my project I used a flag named isUpdatingFromMapDrag. Again, the name is not the point.
The concept is: when the map drag handler is actively pushing values into the form,
temporarily ignore form-driven map updates (or vice versa).
This guard makes the editor stable and prevents accidental recursion.
A small but important rendering detail
When only a marker position changes, I update the existing marker in place
(for example, Leaflet's setLatLng) instead of clearing and re-adding layers.
This avoids flicker and "marker disappeared" bugs.
My cheat sheet
Human-friendly display: often (lat, lon)
GIS engine, GeoJSON, storage: usually (lon, lat)
Practical rule: keep one conversion boundary and forbid manual swapping elsewhere
Editor stability: use an update-direction guard to avoid feedback loops
Final note to future me
If a point suddenly appears in a completely wrong place and there are no errors, check coordinate order first.
If the codebase has a conversion layer, the bug is usually that some new code bypassed it.
After receiving helpful feedback from users monitoring multiple projects, I've added a new enhancement that makes it easier to identify recently sold units, without needing to manually compare listings each time.
What's New: Highlighting Newly Sold Units
The latest update introduces the Newly Sold Unit Indicators feature. It flags units that have recently been marked as "Telah Dijual" (sold) since your last visit. This makes it faster to identify changes, especially for users keeping an eye on specific buildings or units.
Newly sold unit indicator
How It Works
1. Automatic Comparison
When you load a property page, the extension checks for any units that have changed from "available" to "sold" by comparing the current page data with previously stored unit status.
2. Data Storage
The newly sold unit data is saved in Chrome's localStorage under the newlySoldUnits key (in short, what it means is that the data persists even after the browser is closed, and no data is being sent to external servers, no privacy concerns). Each entry contains:
unitNumber: The unique identifier of the unit
dateMarkedSold: The timestamp when the unit was marked as sold (stored in ISO format)
3. Visual Highlight
To make changes easier to spot, units newly marked as sold are styled with:
A light yellow background
Red text and a yellow border
4. UI Panel Updates
The extension popup now includes a dedicated section showing:
The total number of newly sold units
A list of unit numbers
The most recent sold timestamp, e.g., "July 2, 2025, 14:30"
A "Mark as Read" button to clear these highlights after reviewing
5. Persistent Across Sessions
All data remains intact across browser sessions. When you revisit the same project, you'll still see what was previously marked as sold, until you manually clear it.
Why This Matters
Tracking changes in property listings can be tedious, especially when revisiting projects to check what's been taken. With this new feature, users can:
Save time by focusing only on new changes
Improve clarity with color-coded visual indicators
Make informed decisions with real-time updates
What's Next
This update is part of a larger plan to make the extension more intelligent and intuitive. Some upcoming ideas:
Optional desktop notifications for sold updates
A unit history tracker
Multi-project summaries
If you're using the extension and have ideas to improve it, feel free to reach out, feedback is always welcome.
Recap: Key Features in This Update
New Newly Sold Unit Indicators feature
Tracks changes in unit status between visits
Stores sold data in localStorage with timestamps
Visual highlight with yellow background and red text
Extension UI shows sold unit summary with clear date/time
Data remains available until manually cleared
You can install or update the extension from your Chrome browser as usual. Stay tuned for more updates in the future. If you have already installed the extension, it should automatically update to the latest version.
Update: Since the Teduh website was completely revamped, this extension has become unusable. The new site structure is far less URL-friendly, eliminating quick, direct access to individual project information.