An enterprise-grade housing platform with 12 microservices, built to serve the expat housing market in Korea. Supporting four languages (KO/EN/JA/ZH) and multiple currencies, RELO connects foreign residents with quality housing through AI-powered search, integrated payments, and a full-service concierge experience.
- Project Overview
- Tech Stack
- Architecture
- Project Structure
- Getting Started
- Services
- Frontend Apps
- Key Features
- Deployment
- Environment Variables
- API Documentation
- Security
RELO is a bilingual housing platform purpose-built for foreigners relocating to Korea. It addresses the unique challenges expats face when searching for housing in a foreign country: language barriers, unfamiliar lease structures, and lack of trusted intermediaries.
The platform competes in the expat housing market alongside Airbnb and Zigbang, differentiating itself through:
- Multi-language support across Korean, English, Japanese, and Chinese
- Multi-currency payments (KRW, USD, EUR, JPY, CNY, GBP) via TossPayments and Stripe
- AI-powered property recommendations tailored to expat preferences
- End-to-end relocation services including concierge, community forum, and lease management
- Corporate dashboards for companies managing employee relocations
| Layer | Technology |
|---|---|
| Frontend | Next.js 14+ (App Router), TypeScript, Tailwind CSS, TanStack Query, Zustand, next-intl |
| Backend | Python 3.12+, FastAPI, SQLAlchemy (async), Pydantic v2 |
| Database | PostgreSQL 16, Redis 7 |
| Messaging | RabbitMQ (async event bus with REST fallback) |
| Mobile | React Native (Expo) |
| Infra | Docker Compose, nginx, PM2, Let's Encrypt SSL |
| Payments | TossPayments, Stripe |
| Auth | JWT + OAuth 2.0 (Google, Kakao) |
| Monitoring | Sentry (frontend + backend) |
| CI/CD | GitHub Actions, Docker, SSH + rsync deploy |
| IaC | Terraform, Kustomize (Kubernetes) |
| Monorepo | Turborepo, pnpm workspaces |
RELO follows Clean Architecture (4-Layer) on the backend and a monorepo structure managed by Turborepo.
┌─────────────────────────────────────────────────────────┐
│ Clients │
│ Web (3000) │ Admin (3001) │ Mobile (Expo) │
└────────────┬────────────────┬──────────────┬────────────┘
│ │ │
▼ ▼ ▼
┌─────────────────────────────────────────────────────────┐
│ API Gateway (:8000) │
│ Route, Auth Verify, Rate Limit │
└────────────┬────────────────────────────────┬───────────┘
│ │
┌───────┴────────┐ ┌────────┴───────┐
▼ ▼ ▼ ▼
┌─────────┐ ┌──────────────┐ ┌──────────┐ ┌───────────┐
│ Auth │ │ Property │ │ Booking │ │ Payment │
│ Service │ │ Service │ │ Service │ │ Service │
└─────────┘ └──────────────┘ └──────────┘ └───────────┘
┌─────────┐ ┌──────────────┐ ┌──────────┐ ┌───────────┐
│ User │ │ Search │ │ Media │ │ Messaging │
│ Service │ │ Service │ │ Service │ │ Service │
└─────────┘ └──────────────┘ └──────────┘ └───────────┘
┌───────────────┐ ┌───────────────────┐
│ Notification │ │ Concierge │
│ Service │ │ Service │
└───────────────┘ └───────────────────┘
│ │
▼ ▼
┌─────────────────────────────────────────────────────────┐
│ PostgreSQL 16 │ Redis 7 │
└─────────────────────────────────────────────────────────┘
Backend Layer Structure (per service):
services/{service}/app/
├── api/ # FastAPI routes, request/response schemas
├── application/ # Use cases, business orchestration
├── domain/ # Entities, repository interfaces (ABCs), value objects
└── infrastructure/ # Repository implementations, external integrations
- Repository Pattern: Abstract interfaces in
domain/, implementations ininfrastructure/ - Dependency Injection: Via FastAPI
Depends - Inter-service communication: REST (synchronous) via internal URLs, plus a RabbitMQ event bus for async events (
services/shared/event_bus.py) that degrades gracefully to REST when the broker is unavailable - Internal APIs:
/internal/prefix, secured withX-Internal-Tokenheader
relo/
├── apps/
│ ├── web/ # User-facing Next.js app (port 3000)
│ ├── admin/ # Admin dashboard Next.js app (port 3001)
│ └── mobile/ # React Native (Expo) mobile app
├── packages/
│ ├── api-client/ # Shared API client library
│ ├── config/ # Shared configuration (ESLint, TypeScript)
│ └── ui/ # Shared UI component library
├── services/
│ ├── gateway/ # API Gateway - routing, auth verification
│ ├── auth/ # Authentication & authorization
│ ├── user/ # User profiles & preferences
│ ├── property/ # Property listings & management
│ ├── search/ # Search engine & AI recommendations
│ ├── booking/ # Booking lifecycle & availability
│ ├── payment/ # Payment processing & escrow
│ ├── notification/ # Email, push, in-app notifications
│ ├── concierge/ # Concierge & relocation services
│ ├── media/ # Image/file upload & CDN management
│ ├── messaging/ # Real-time chat between users
│ └── shared/ # Shared Python utilities & base classes
├── infra/
│ ├── terraform/ # Infrastructure as Code
│ ├── k8s/ # Kubernetes manifests
│ └── lambda/ # AWS Lambda functions
├── scripts/ # Database init, deployment scripts
├── tests/ # End-to-end & integration tests
├── docs/ # Design docs, requirements, reports
├── .github/ # CI/CD workflows, auto-fix config
├── docker-compose.yml # Local development orchestration
├── turbo.json # Turborepo pipeline configuration
├── pnpm-workspace.yaml # pnpm workspace definition
└── playwright.config.ts # E2E test configuration
| Tool | Version |
|---|---|
| Node.js | 18+ |
| Python | 3.12+ |
| Docker | 24+ |
| pnpm | 9+ |
# 1. Clone the repository
git clone https://github.com/your-org/relo.git
cd relo
# 2. Install frontend dependencies
pnpm install
# 3. Set up environment variables
cp .env.example .env
# Edit .env with your configuration (see Environment Variables section)
# 4. Start backend services (PostgreSQL, Redis, all microservices)
docker compose up -d
# 5. Start frontend development servers
pnpm devThe web app will be available at http://localhost:3000, the admin dashboard at http://localhost:3001, and the API gateway at http://localhost:8000.
# Check gateway health
curl http://localhost:8000/health
# Check all containers
docker compose psRELO is composed of 12 microservices, all orchestrated through the API Gateway.
| # | Service | Description | Redis DB |
|---|---|---|---|
| 1 | Gateway | API Gateway - routing, authentication, rate limiting | 0 |
| 2 | Auth | JWT auth, OAuth (Google/Kakao), token blacklisting | 0 |
| 3 | User | User profiles, preferences, role management | 1 |
| 4 | Property | Property listings, host management, amenities | 2 |
| 5 | Media | Image/file uploads, S3 storage, CDN delivery | 3 |
| 6 | Search | Full-text search, filters, AI recommendations | 4 |
| 7 | Booking | Booking lifecycle, availability, min stay rules | 5 |
| 8 | Payment | TossPayments/Stripe, escrow, settlements | 6 |
| 9 | Notification | Email, SMS (Aligo), push, in-app notification dispatch | 7 |
| 10 | Concierge | Relocation services, housing requests, support | 8 |
| 11 | Messaging | Real-time chat between hosts and guests | 9 |
| 12 | Shared (library) | Common utilities, base models, Sentry integration | -- |
All services expose a GET /health endpoint for monitoring. Internal inter-service calls use the /internal/ prefix secured by X-Internal-Token.
The user-facing application built with Next.js 14 App Router.
- Internationalization: next-intl for KO/EN/JA/ZH
- State management: TanStack Query (server), Zustand (client)
- UI: Tailwind CSS, Lucide icons
- Maps: Google Maps integration for property search
- Analytics: Google Analytics 4 (gtag) for usage tracking
- Monitoring: Sentry for error tracking
The administrative dashboard for platform operators and hosts.
- UI Framework: Radix UI primitives + shadcn/ui patterns
- Charts: Recharts for analytics and reporting
- Forms: React Hook Form + Zod validation
The mobile companion app built with React Native and Expo.
- Full i18n support: Korean, English, Japanese, Chinese
- Dynamic currency conversion: KRW, USD, EUR, JPY, CNY, GBP
- Map-based search with Google Maps
- Advanced filters (location, price, type, amenities)
- AI-powered property recommendations
- Availability calendar with real-time updates
- Minimum stay enforcement per property
- Dual payment gateway: TossPayments (domestic) + Stripe (international)
- Escrow system for secure transactions
- Host application and verification workflow
- Property listing creation and management
- Booking management and calendar sync
- Settlement tracking and payout analytics
- Corporate dashboard for employee relocation management
- Bulk booking and invoicing
- Employee housing allocation and tracking
- Community forum for expats
- Housing request board
- Concierge services for relocation assistance
- Real-time messaging between hosts and guests
- Verified review system
- Dispute resolution workflow
- Lease management and documentation
- OAuth 2.0 via Google and Kakao
- JWT authentication with refresh tokens
- Token blacklisting for secure logout
RELO is deployed on AWS EC2 with the following stack:
Internet
│
▼
nginx (reverse proxy + SSL termination)
│
├── / → Next.js Web (PM2, port 3000)
├── /admin → Next.js Admin (PM2, port 3001)
└── /api/ → API Gateway (Docker, port 8000)
│
├── 10 microservices (Docker)
├── PostgreSQL 16 (Docker)
└── Redis 7 (Docker)
- SSL: Let's Encrypt with auto-renewal
- Process Management: PM2 for Next.js apps
- Container Orchestration: Docker Compose for backend services
- CI/CD: GitHub Actions -- lint, type-check, build, deploy via SSH + rsync
- Health Checks: Automated post-deploy verification on all service ports
Create a .env file in the project root. Required variables:
# ── Core ─────────────────────────────────────────────
JWT_SECRET_KEY= # Required: JWT signing secret
APP_ENV= # development | staging | production
# ── Database ─────────────────────────────────────────
DATABASE_URL= # PostgreSQL connection string
REDIS_PASSWORD= # Redis authentication password
# ── OAuth ────────────────────────────────────────────
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
KAKAO_CLIENT_ID=
KAKAO_CLIENT_SECRET=
# ── Payments ─────────────────────────────────────────
TOSS_SECRET_KEY= # TossPayments API secret
STRIPE_SECRET_KEY= # Stripe API secret
# ── AWS / Media ──────────────────────────────────────
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_REGION= # Default: ap-northeast-2
S3_BUCKET_NAME= # S3 bucket for media uploads
CDN_BASE_URL= # CloudFront distribution URL
# ── AI ───────────────────────────────────────────────
OPENAI_API_KEY= # For AI-powered recommendations
# ── Monitoring ───────────────────────────────────────
SENTRY_DSN= # Sentry error tracking DSN
# ── CI/CD (GitHub Secrets) ───────────────────────────
EC2_SSH_KEY= # Deployment SSH private key
EC2_HOST= # EC2 instance hostname
EC2_USER= # EC2 SSH username
SLACK_WEBHOOK_URL= # Slack notification webhook
ANTHROPIC_API_KEY= # Claude auto-fix integrationhttp://localhost:8000/api/v1/
| Prefix | Service | Description |
|---|---|---|
/api/v1/auth |
Auth | Login, register, OAuth, token refresh |
/api/v1/users |
User | Profile, preferences, roles |
/api/v1/properties |
Property | Listings CRUD, amenities, host tools |
/api/v1/search |
Search | Property search, filters, AI suggest |
/api/v1/bookings |
Booking | Create, manage, cancel bookings |
/api/v1/payments |
Payment | Initiate payment, escrow, settlement |
/api/v1/notifications |
Notification | Notification preferences, history |
/api/v1/concierge |
Concierge | Service requests, housing requests |
/api/v1/media |
Media | File upload, image management |
/api/v1/messages |
Messaging | Chat threads, real-time messaging |
Each service also exposes interactive API docs at its internal port:
- Swagger UI:
http://localhost:{port}/docs - ReDoc:
http://localhost:{port}/redoc
| Measure | Implementation |
|---|---|
| Authentication | JWT with access/refresh tokens, token blacklisting via Redis |
| Password Hashing | bcrypt via passlib |
| Rate Limiting | Redis-backed rate limiting at the API Gateway |
| CORS | Whitelist-based origin policy |
| Security Headers | HSTS, CSP, X-Frame-Options, X-Content-Type-Options |
| Internal APIs | X-Internal-Token header for inter-service calls |
| Secrets Management | Environment variables, no hardcoded secrets |
| Input Validation | Pydantic v2 schemas on all API endpoints |
| OAuth 2.0 | Google and Kakao social login |
| Error Monitoring | Sentry with service-level tags and alerting |
Built with care for the global community in Korea.