Full-Stack · 2025
StayEase
A stay-reservation app with geo search, listings, and bookings.
StayEase media, 2 items. Use the arrow keys to move.
Illustration. Not a screenshot of the app.
I built StayEase so finding a place to stay could start from where the place actually is, not from whether the city name happened to match the words I typed.
The problem
A stay search that matches a city string will happily return the wrong neighborhood, or miss a place nearby because the listing wrote the neighborhood instead of the city. Uploading a stay, taking it down, and reserving it were the other half of the same job. A catalog you cannot edit, and a search you cannot trust, are both useless.
The person it frustrates is the one trying to list a room and the one trying to book it. One of them needs the photos, the record, and a way to delete a listing that is no longer real. The other needs a search that starts from a point on the map. It was worth solving because a reservation that is only a text match is a reservation in the wrong place.
How I built it
The screen is React and Ant Design. Listing, searching, and reserving are forms and lists, and Ant Design already had those pieces. The work was making the search geographic, not inventing a new set of buttons.
The API is Spring Boot. It is what takes an upload, a deletion, a search, and a reservation. User data, the stay itself, and the reservation history sit in PostgreSQL. A stay has a location, so the location is indexed with PostGIS. A search can start from a point instead of from a string compare on a city name. That is the whole reason the geo index is there.
Photos do not belong in the database row. Google Cloud Storage takes the media uploads, and the row keeps the stay. Sign-in is Spring Security with a JWT, so a reservation is tied to an account and the token is what the API checks.
The React site is a static frontend on AWS Amplify. The Spring Boot service is the piece that talks to PostgreSQL, PostGIS, and Cloud Storage. Docker is how that service is packaged.
Challenges and what I learned
The search is only as good as the location stored on the stay. A city name in a text column would have been easier, and it would have brought back the problem I was trying to leave. PostGIS is there so the query can start from a point. The other split was the photo. Keeping media in Cloud Storage, and the stay and the reservation history in PostgreSQL, meant a listing could be deleted without treating the image as the record.

Let's talk ↗









