Repository navigation
Rewrite the backend in TypeScript with PostGIS location search - #1
Merged
Merged
Conversation
The C++ backend searched by place only through free-text Nominatim
geocoding ("метро Тверская" landed on the Okhotny Ryad bus stop), ignored
the user's own location, silently dropped the location when geocoding
failed and ranked venues inside the radius without looking at distance.
The new backend (Node 24, Fastify, zod, PostgreSQL + PostGIS) works
algorithm first:
- a rule parser with a vocabulary of categories, cuisines, moods, company,
features and budgets and a gazetteer of 240 metro stations and 132
district polygons from OpenStreetMap, matched by word stems;
- search with ST_DWithin around a station, a landmark or the user, or
inside a district polygon, widening 800 m to 4 km before relaxing the
category, with notes that say what happened;
- ranking by wishes, taste and distance, one branch per chain.
GigaChat is narrow: it interprets a query only when the rules found
nothing or a place stayed unresolved, its answer is checked against
closed lists, it may only reorder the top 10 candidates, and an
unreachable service is paused for two minutes. Nominatim stays as a
cached fallback with the same pause.
The Mini App gets a Near me button (Telegram LocationManager, browser
geolocation outside Telegram), a line that explains where it searches,
distances on cards, and renders venue data with textContent.
Nominatim is slow and was unreachable for long stretches, so a query like "ресторан у Большого театра" depended on a network call. The gazetteer now also holds 667 notable landmarks from OpenStreetMap (theatres, museums, parks, gardens, stadiums, squares with a Wikidata link inside the MKAD) with their alternative names, matched by word stems like stations: "у Большого театра", "в парке Горького", "у Патриарших прудов" resolve without the network. A station still wins over a landmark of the same name. Nominatim remains the fallback.
The README opens like the app: a banner in its own design language (dark ground with lime blobs, Sekuya title, a mock of the search pill, the context line and a swipe card for a real bar 60 m from Tverskaya), light and dark variants picked by the GitHub theme, text outlined so no fonts or scripts load, 64 KB each with glyphs reused through <use>. Below it: call to action and stack badges, a navigation row, a table of real queries and what the app answers, a Mermaid diagram of the search and collapsible sections for Telegram setup, the API, data, structure and tests.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Stage 1 of the plan: search by location that actually works, on a TypeScript backend instead of C++.
The old search found the place only through free-text Nominatim geocoding ("метро Тверская" landed on the Okhotny Ryad bus stop, so the 800 m circle moved almost a full radius), never used the user's own location, silently searched the whole city when geocoding failed and ranked venues inside the radius without looking at distance.
Now the algorithm does the work and GigaChat has a narrow role:
notesin the response say what happened.Changes
backend/: Node 24, Fastify 5, zod, PostgreSQL 16 + PostGIS; migrations, rule parser and gazetteer, ranking, search and taste services, GigaChat and Nominatim adapters,places:fetchanddb:loadscripts. The C++ backend andload_to_db.pyare removed.db/Dockerfile: PostgreSQL 16 with PostGIS that runs natively on Apple Silicon;docker-compose.ymlbuilds it on the same data volume.frontend/: Near me button (Telegram LocationManager, browser geolocation outside Telegram), a line that explains where the search went, distances on cards, venue data rendered withtextContent.Testing
npm run lintandnpm run typecheckpass.ranked_by: "llm").After merging, run
docker compose up -d --buildandcd backend && npm ci && npm run db:loadonce: the database image now includes PostGIS and the schema is migrated on start.