Платформа аренды жилья в Азербайджане (AZ/RU/EN) на React + TypeScript + Firebase.
Этот гайд покрывает полную миграцию проекта на Firebase и настройку проекта с нуля.
- ARCHITECTURE.md - Project structure, services, setup requirements
- SERVICES.md - Available services and how to use them
- SETUP_CUSTOM_CLAIMS.md - Firebase moderator role setup
- Каталог объектов на главной загружается из Firestore.
- Страница объекта загружает объект по id из Firestore.
- Личный кабинет пользователя работает с Firestore:
- просмотр своих объявлений,
- добавление объявлений,
- загрузка фото в Firebase Storage,
- удаление объявлений.
- Аутентификация и регистрация работают через Firebase Authentication.
- React 18
- TypeScript 5
- Vite
- React Router DOM 6
- Firebase (Auth, Firestore, Storage)
- React Leaflet + OpenStreetMap
- Cloudflare Pages
npm installСоздайте файл .env:
- Linux/macOS:
cp .env.example .env- Windows PowerShell:
Copy-Item .env.example .envЗапуск:
npm run devСборка:
npm run buildПредпросмотр сборки:
npm run preview- Откройте https://console.firebase.google.com/
- Нажмите Create a project.
- Назовите проект, например birklik-az.
- Google Analytics можно выключить (необязательно).
- Внутри проекта нажмите Add app -> Web (</>).
- Укажите имя приложения, например birklik-web.
- Получите объект firebaseConfig.
Скопируйте значения из firebaseConfig в .env:
VITE_FIREBASE_API_KEY=your_api_key
VITE_FIREBASE_AUTH_DOMAIN=your_project.firebaseapp.com
VITE_FIREBASE_PROJECT_ID=your_project_id
VITE_FIREBASE_STORAGE_BUCKET=your_project.appspot.com
VITE_FIREBASE_MESSAGING_SENDER_ID=your_sender_id
VITE_FIREBASE_APP_ID=your_app_id- Firebase Console -> Build -> Authentication.
- Нажмите Get started.
- Sign-in method -> Email/Password -> Enable.
- Authentication -> Settings -> Authorized domains:
- добавьте
birklik.az - добавьте
www.birklik.az(если используется) - добавьте ваш Cloudflare preview домен (
*.pages.devпроектный домен)
Без этого Firebase будет показывать предупреждение про OAuth redirect domain и popup/redirect провайдеры не будут работать на вашем домене.
TEST
- Firebase Console -> Build -> Firestore Database.
- Create database.
- Выберите Production mode.
- Выберите регион (лучше ближе к вашим пользователям).
- Firebase Console -> Build -> Storage.
- Get started.
- Выберите тот же регион.
Коллекции:
- users/{uid}
- properties/{propertyId}
Пример users/{uid}:
{
"name": "Test User",
"email": "test@example.com",
"phone": "+994501112233",
"avatar": "https://...",
"createdAt": "2026-03-16T10:00:00.000Z"
}Пример properties/{propertyId}:
{
"type": "villa",
"district": "mardakan",
"price": {
"daily": 250,
"weekly": 1500,
"monthly": 6000,
"currency": "AZN"
},
"rooms": 4,
"area": 220,
"amenities": ["pool", "wifi", "parking"],
"images": ["https://..."],
"coordinates": { "lat": 40.4093, "lng": 49.8671 },
"title": {
"az": "Başlıq",
"ru": "Заголовок",
"en": "Title"
},
"description": {
"az": "Təsvir",
"ru": "Описание",
"en": "Description"
},
"address": {
"az": "Ünvan",
"ru": "Адрес",
"en": "Address"
},
"owner": {
"name": "Test User",
"phone": "+994501112233",
"email": "test@example.com"
},
"ownerId": "firebase_uid",
"isFeatured": false,
"isActive": true,
"city": "Baku",
"createdAt": "2026-03-16T10:00:00.000Z",
"updatedAt": "2026-03-16T10:00:00.000Z"
}Firebase Console -> Firestore -> Rules:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId} {
allow read: if request.auth != null;
allow create, update, delete: if request.auth != null && request.auth.uid == userId;
}
match /properties/{propertyId} {
allow read: if true;
allow create: if request.auth != null
&& request.resource.data.ownerId == request.auth.uid
&& request.resource.data.type is string
&& request.resource.data.district is string
&& request.resource.data.price.daily is number
&& request.resource.data.rooms is number;
allow update, delete: if request.auth != null
&& resource.data.ownerId == request.auth.uid;
}
}
}Firebase Console -> Storage -> Rules:
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /properties/{allPaths=**} {
allow read: if true;
allow write: if request.auth != null;
}
match /avatars/{userId}/{allPaths=**} {
allow read: if true;
allow write: if request.auth != null
&& request.auth.uid == userId
&& request.resource.size < 5 * 1024 * 1024
&& request.resource.contentType.matches('image/.*');
}
}
}Для текущих запросов нужны композитные индексы в коллекции properties.
Откройте Firebase Console -> Firestore -> Indexes -> Composite -> Create index и добавьте:
- type Asc, createdAt Desc
- district Asc, createdAt Desc
- ownerId Asc, createdAt Desc
- isFeatured Asc, createdAt Desc
- type Asc, price.daily Asc, createdAt Desc
- district Asc, price.daily Asc, createdAt Desc
Примечание: если Firebase вернет ссылку на конкретный индекс в ошибке запроса, просто откройте эту ссылку и создайте индекс в 1 клик.
- Запустите проект: npm run dev.
- Зарегистрируйте пользователя.
- Войдите в Dashboard.
- Создайте объявление и прикрепите фото.
- Проверьте:
- документ появился в Firestore -> properties,
- фото появилось в Storage -> properties/,
- объявление видно в списке Dashboard,
- объявление видно на главной,
- карточка открывается по маршруту /property/:id.
- Push в репозиторий.
- Cloudflare Dashboard -> Workers & Pages -> Create application.
- Connect to Git.
- Build command: npm run build.
- Build output: dist.
- Добавьте все переменные VITE_FIREBASE_* в Environment Variables.
- Deploy.
npm install -g wrangler
wrangler login
npm run build
wrangler deployВ этом проекте используется современный режим Wrangler static assets через wrangler.toml, поэтому wrangler deploy публикует папку dist как статический сайт с SPA fallback.
-
Ошибка Missing or insufficient permissions:
- проверьте Firestore Rules,
- проверьте ownerId в документе.
-
Ошибка index required:
- создайте индекс по ссылке из ошибки.
-
Картинки не загружаются:
- проверьте Storage Rules,
- проверьте, что пользователь авторизован.
-
Пустой каталог:
- проверьте, есть ли документы в properties,
- проверьте .env и корректный projectId.
src/
components/
config/
context/
data/
i18n/
layouts/
pages/
services/
styles/
types/
Если нужно, могу сделать второй этап миграции:
- редактирование объявления (update) прямо из Dashboard,
- геокодинг адреса и автоматическая установка coordinates,
- полноценный production-поиск через Algolia (вместо client-side фильтра).
Birklik.az — это маркетплейс краткосрочной аренды жилья в Азербайджане.
- Владельцы жилья публикуют объявления на платформе.
- Публикация может быть в разных пакетах (например: free, standard, premium).
- Платные пакеты дают больше видимости и возможностей для объявления.
- Гость открывает каталог и использует поиск/фильтры.
- Переходит в карточку объекта, смотрит фото, описание, цену и карту.
- Отправляет заявку через форму контакта владельцу.
- Регистрируется и заходит в Dashboard.
- Создает объявление, заполняет параметры, добавляет фото и локацию.
- Объявление сохраняется в Firestore, фото — в Storage.
- Владелец управляет своими объявлениями из личного кабинета.
- Frontend: React + TypeScript + Vite.
- Auth: Firebase Authentication.
- Данные: Firestore.
- Файлы: Firebase Storage.
- Карта: OpenStreetMap + React Leaflet. test Vite Сборка До PWA до Capacitor есть чат с Клаудом спец для этого Google Search Invented calilorucli42@gmail.com Google ReCaptcha ИнВент Надо Для всех Приложений Yandex Карты Добавлены Все Ключи либо в Claudflare либо в ENV Google Business profile invented calilorucli42@gmail.com business gmail info@birklik.az Google Cloud + Firebase trello+ BirCard Azerbaijan Bank give approve for integration the Bank payment in gmail calilorucli42@gmail.com approve + Важно Azericard : RSA Keys внутри Проекта и подключен Cloud Funtions в Папке Firebase Functions Token problem ctrl f5 solve with Cache (purge everything Cloudflare)