Sync
On-demand services marketplace
A marketplace connecting customers with local providers for dispatch, cleaning, errands, home services, beauty and laundry. Two sides of the same app: customers book, providers onboard, set their areas and get paid.
- Customer and provider roles in one Expo app
- Provider onboarding, verification and service areas
- Bookings with saved addresses and job tracking
- OTP authentication and payouts to bank accounts
A two-sided marketplace where both roles share one Expo client against a Django REST backend split into seven apps. The only project here with a full test, typing and lint toolchain pinned alongside the runtime dependencies.
- Django
- DRF
- PostgreSQL
- Expo
- React Native
- OTP auth
How it is built
A two-sided marketplace where both roles share one Expo client against a Django REST backend split into seven apps. The only project here with a full test, typing and lint toolchain pinned alongside the runtime dependencies.
Stack
- Django 5.2 backend
- DRF 3.18 backend
- Simple JWT backend
- drf-spectacular backend
- Argon2 backend
- PostgreSQL (psycopg 3) data
- Redis data
- Celery backend
- Gunicorn infra
- Docker infra
- Expo client
- React Native client
- React Native Maps client
- Zustand client
- React Query client
Architecture
One client serving two roles, against a backend split by marketplace concern, with background work on a queue.
-
Expo client
client
Customer and provider experiences in one binary
- Expo Router
- React Query
- Zustand
- React Native Maps
-
Django REST API
service
- DRF
- drf-spectacular
-
Accounts
service
- Simple JWT
- Argon2
- phonenumbers
- Providers service
- Catalogue service
- Bookings service
- Payments service
- Notifications service
- Celery workers service
- Redis datastore Broker for the task queue
- PostgreSQL datastore
Flow
- Expo client Django REST API HTTPS
- Django REST API Accounts
- Django REST API Providers
- Django REST API Catalogue
- Django REST API Bookings
- Django REST API Payments
- Django REST API Notifications
- Django REST API Redis Enqueue
- Redis Celery workers
- Celery workers PostgreSQL
- Django REST API PostgreSQL
Data
PostgreSQL
- Accessed through psycopg 3
- Redis alongside it as the Celery broker
Authentication
JSON Web Tokens
- Simple JWT for session tokens
- Argon2 password hashing rather than Django's default
- Phone numbers parsed and validated with phonenumbers
Testing
- pytest with pytest-django and factory-boy
- Coverage measured as part of the dev extra
- Ruff for linting, mypy with django-stubs and DRF stubs for typing
Infrastructure
- Dockerfile and a Docker Compose definition for local services
- GitHub Actions workflows in the repository
- Dependencies pinned exactly and verified together against one interpreter
- Served by Gunicorn
Notable decisions
-
Pin every dependency exactly and verify them as a set
A marketplace taking payments cannot afford a surprise transitive upgrade
-
Argon2 instead of Django's default password hasher
Memory-hard hashing is the current recommendation for stored credentials
-
Celery on Redis for work that must not block a request
Notifications and payout processing are slow and retryable, so they leave the request cycle