StayMap Polska
A full-stack accommodation booking platform in Poland with a map-first approach, Polish AI search and real-time communication.
12
Django modules
44
Next.js views
25
test files
9
travel modes
DEMO
Product in practice
Key project views showing map-first search, the booking flow, the host panel and real-time communication.
What you can check in the demo
accommodation search on the map
offer filtering
travel modes
host panel
booking flow
Polish AI search
real-time chat
Swagger/OpenAPI documentation
ORIGIN
Product problem
StayMap was created as a response to the problem of accommodation search, where location, price, availability and user needs are often scattered across different screens and filters.
Map as the main interface
In many platforms, the map is only an addition to the results list. In StayMap, location is the starting point — users discover offers directly on the map.
Pricing without seasonal context
Accommodation prices depend on dates, length of stay, season, holidays and number of guests. The dynamic pricing engine handles these rules in one consistent process.
Fragmented user journey
Guests, hosts and administrators often work in separate workflows. StayMap connects search, booking, communication, host management and moderation in one system.
SCOPE
My role in the project
This was an individual project — I designed and built the full application myself: backend, API, data model, business logic, integrations, frontend and live demo deployment.
Backend architecture
I designed the structure of 12 Django modules, model relationships, permission system and the booking lifecycle.
REST API + WebSocket
I built 47 DRF endpoints with Swagger/OpenAPI documentation and an ASGI layer with Daphne handling both REST and WebSocket communication.
Data and geolocation
I designed the PostgreSQL/PostGIS database schema, spatial queries, geographic indexes and location-based offer search.
Async tasks and integrations
I added Celery tasks, Redis in multiple roles, OpenAI integration, Google OAuth, transactional email and external location data sources.
DESIGN
System architecture
The architecture is split into layers: Next.js frontend, Django/DRF backend, WebSocket communication through Channels, PostgreSQL/PostGIS database and asynchronous background tasks with Celery.
Client
Browser and mobile users interacting with the booking platform.
Frontend
User interface, routing, views and BFF proxy layer.
API Layer
REST API, business logic, authentication and API contract documentation.
Real-time
WebSocket communication for chat and real-time status updates.
Data & Geo
Data model, bookings, location and spatial queries.
Async & Integrations
Background jobs, cache, AI search and external integrations.
Why this architecture?
BFF proxy in Next.js
The frontend does not communicate directly with the backend. The proxy layer helps control requests, authentication and API structure.
ASGI for REST + WebSocket
Daphne makes it possible to handle standard HTTP requests and real-time chat within one application architecture.
PostGIS for location-based search
Location is the core of the product, so spatial queries are part of the data model instead of being an external add-on.
Redis in multiple roles
Redis handles cache, Celery broker and the WebSocket channel layer while keeping responsibilities logically separated.
FEATURES
Key technical features
Map-first UX + PostGIS
Geospatial accommodation search built with GeoDjango and PostGIS 3.4. Spatial queries, distance filtering, location-based ranking and integration with Nominatim and Overpass API.
Dynamic Pricing Engine
Multi-layer pricing engine: seasons, Polish holidays, weekends, extra guest fees and long-stay discounts. The final price is saved as a snapshot at the moment of booking.
Polish AI Search
OpenAI API interprets user queries in Polish and maps user intent to search filters. AI sessions include TTL and cost limits.
Real-time Chat
Django Channels + Daphne ASGI. WebSocket events: message.new, typing.start, typing.stop and message.read. Connection authorization is based on JWT.
Blind Reviews
Reviews are published only when both sides — guest and host — submit their opinion. This limits the influence of one review on the other and makes the process fairer.
Auth + Security
JWT with token rotation and HTTP-only cookies, Google OAuth, upload validation and rate limiting for AI, auth and upload endpoints.
CHALLENGES
Hardest problems to solve
Areas where the project required real technical decisions.
Redis in 3 roles
Redis had to work as application cache, Celery message broker and Django Channels layer at the same time, with proper database separation to avoid mixing data.
Separate Redis databases: db=0 for cache, db=1 for Celery, db=2 for Channels. Docker Compose health checks ensure Redis starts before the application.
ASGI + WSGI
Moving from WSGI to ASGI required understanding how HTTP request routing and WebSocket routing can work together in one application process.
asgi.py configuration with URLRouter for Channels and Django application wrapper for standard HTTP requests. Daphne as the main application server.
Dynamic pricing
Multiple pricing rules can overlap for the same date range: season, holiday, weekend and long-stay. The order of applying rules affects the final price.
Rule priority system with explicit order: base → season → holiday → extra guests → long-stay discount. Price snapshot saved atomically when creating a booking.
LEARNINGS
What I learned
ASGI vs WSGI architecture and when to use each of them
Geospatial queries with PostGIS — from theory to spatial indexes
BFF pattern in Next.js as a proxy layer between frontend and API
Managing complex booking state, deadlines and lifecycle
Redis as a multi-purpose tool — cache, broker and channel layer
Error monitoring, structured logging and thinking about application observability
ROADMAP
Planned product extensions
Features that naturally develop StayMap into a more complete travel product.
Interested in this project?
I would be happy to talk more about the technical decisions, architecture and problems I solved while building it.