Frontend - Silent Meadow¶
Обзор¶
Современный фронтенд платформы Silent Meadow, построенный на React 18 + TypeScript + TailwindCSS. Следует трендам дизайна 2026 года и реализует концепцию "Сбалансированная Цифровая Природа" - сочетание минимализма, природной эстетики и современных технологий.
Технологический стек¶
Core¶
- React 18.2 - UI библиотека
- TypeScript 5.3 - типизация
- Vite 5 - сборщик (быстрее Webpack)
- TailwindCSS 3.4 - utility-first стилизация
State Management¶
- React Query (TanStack) 5.20 - server state + кэширование API
- Zustand 4.5 - локальное UI состояние (фильтры, модалы)
UI Libraries¶
- Framer Motion 11 - анимации и переходы
- @pbe/react-yandex-maps 1.2 - интеграция Яндекс.Карт
- Swiper 11 - карусели и галереи
- Sonner 1.4 - toast notifications
Forms¶
- React Hook Form 7.50 - управление формами
- Zod 3.22 - валидация схем
- @hookform/resolvers 3.3 - интеграция RHF + Zod
Routing¶
- React Router 6.22 - навигация и routing
Utils¶
- Axios 1.6 - HTTP клиент
- date-fns 3.3 - работа с датами
- clsx 2.1 - условные CSS классы
- tailwind-merge 2.2 - слияние Tailwind классов
Структура проекта¶
frontend/
├── public/
│ ├── fonts/ # Geist, Inter шрифты
│ ├── images/ # Статические изображения
│ └── favicon.ico
│
├── src/
│ ├── main.tsx # Entry point
│ ├── App.tsx # Root компонент + routing
│ ├── vite-env.d.ts # Vite типы
│ │
│ ├── components/
│ │ ├── ui/ # UI Primitives
│ │ │ ├── Button.tsx # 4 варианта: primary, secondary, ghost, glass
│ │ │ ├── Card.tsx # 3 варианта: solid, glass, elevated
│ │ │ ├── Input.tsx # Floating label, валидация
│ │ │ ├── Badge.tsx # Статусы и теги
│ │ │ ├── Skeleton.tsx # Loading states
│ │ │ └── index.ts # Barrel export
│ │ │
│ │ ├── layout/ # Layout компоненты
│ │ │ ├── Header.tsx # Навигация
│ │ │ ├── Footer.tsx
│ │ │ └── MobileNav.tsx # Bottom tab bar
│ │ │
│ │ ├── PropertyCard.tsx # Domain компоненты
│ │ ├── YandexMapView.tsx # Яндекс.Карты с 436 маркерами
│ │ ├── FilterPanel.tsx # Фильтры карты
│ │ ├── HouseCard.tsx # Карточка дома
│ │ └── EmptyState.tsx # Empty states
│ │
│ ├── pages/ # Страницы (routes)
│ │ ├── PropertiesPage.tsx # Главная - карта участков
│ │ ├── HousesPage.tsx # Каталог домов
│ │ ├── AvitoAdsPage.tsx # Управление объявлениями Avito
│ │ ├── LeadsPage.tsx # CRM дашборд
│ │ └── NotFoundPage.tsx # 404
│ │
│ ├── hooks/ # Custom React hooks
│ │ ├── useProperties.ts # React Query - участки
│ │ ├── useDebounce.ts # Debounce hook
│ │ └── useMediaQuery.ts # Responsive breakpoints
│ │
│ ├── lib/ # Библиотеки и утилиты
│ │ ├── api/
│ │ │ ├── client.ts # Axios instance
│ │ │ ├── properties.ts # GET /v1/properties
│ │ │ └── yandex-maps.ts # GET /v1/map/properties
│ │ ├── animations.ts # Framer Motion presets
│ │ ├── utils.ts # Helpers
│ │ └── formatters.ts # formatPrice, formatDate
│ │
│ ├── store/ # State management (Zustand)
│ │ ├── filterStore.ts # Фильтры карты
│ │ └── uiStore.ts # UI state (modals, drawers)
│ │
│ ├── types/ # TypeScript types
│ │ ├── property.ts
│ │ ├── house.ts
│ │ └── api.ts
│ │
│ ├── styles/ # Global styles
│ │ ├── index.css # Tailwind imports + globals
│ │ ├── animations.css # Keyframes
│ │ └── fonts.css # Font-face declarations
│ │
│ └── router/ # React Router config
│ └── index.tsx # Routes configuration
│
├── .env.example # Environment variables template
├── .env.development # Dev environment
├── index.html # HTML entry point
├── package.json # Dependencies
├── tailwind.config.js # Дизайн-система Meadow Digital
├── tsconfig.json # TypeScript config
├── vite.config.ts # Vite config (aliases, proxy)
└── README.md
Дизайн-система: Meadow Digital¶
Цветовая палитра¶
Primary (зелёные акценты природы)¶
--meadow-green-50: #f0f9f4 /* Утренняя роса - светлые фоны */
--meadow-green-100: #dcf3e5 /* Светлая трава - hover states */
--meadow-green-300: #86d5a8 /* Свежая зелень - вторичные кнопки */
--meadow-green-500: #34b574 /* Основной зелёный - CTA кнопки */
--meadow-green-700: #2a8f5c /* Тёмная зелень - hover на CTA */
--meadow-green-900: #1e6342 /* Лесной мох - акценты */
Neutral (earth tones)¶
--stone-50: #fafaf9 /* Белый камень - основной фон */
--stone-100: #f5f5f4 /* Светлый песок - карточки */
--stone-200: #e7e5e4 /* Песчаник - borders */
--stone-500: #78716c /* Глина - вторичный текст */
--stone-900: #1c1917 /* Чёрная почва - основной текст */
Accent (функциональные цвета)¶
--sky-blue: #0ea5e9 /* Интерактивные элементы, ссылки */
--emerald-500: #10b981 /* Доступно, успех */
--amber-500: #f59e0b /* Скидки, спецпредложения */
--red-500: #ef4444 /* Продано, ошибки */
Glassmorphism эффекты¶
--glass-bg: rgba(255, 255, 255, 0.75)
--glass-border: rgba(255, 255, 255, 0.3)
--glass-shadow: 0 8px 32px rgba(0, 0, 0, 0.08)
--glass-blur: blur(16px)
Типографика¶
Font Stack¶
- Primary: Geist (UI, заголовки) - modern geometric sans-serif
- Secondary: Inter (body текст) - максимальная читаемость
- Mono: Geist Mono (цены, кадастровые номера)
Type Scale (модульная шкала 1.250)¶
Hero: 3.815rem (61px) - героические заголовки
H1: 3.052rem (49px) - главные заголовки
H2: 2.441rem (39px) - заголовки секций
H3: 1.953rem (31px) - подзаголовки
Lead: 1.25rem (20px) - лид-текст
Base: 1rem (16px) - основной текст
Small: 0.8rem (13px) - вторичный текст
Font Weights¶
- Light (300) - lead text
- Normal (400) - body
- Medium (500) - UI elements
- Semibold (600) - subheadings
- Bold (700) - headings
Spacing (8pt grid)¶
--space-1: 0.25rem /* 4px */
--space-2: 0.5rem /* 8px */
--space-3: 0.75rem /* 12px */
--space-4: 1rem /* 16px */
--space-6: 1.5rem /* 24px */
--space-8: 2rem /* 32px */
--space-12: 3rem /* 48px */
--space-16: 4rem /* 64px */
Shadows¶
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05)
--shadow-md: 0 4px 6px rgba(0, 0, 0, 0.07)
--shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.1)
--shadow-xl: 0 20px 25px rgba(0, 0, 0, 0.15)
--shadow-glass: 0 8px 32px rgba(0, 0, 0, 0.08)
Border Radius¶
--radius-sm: 0.375rem /* 6px */
--radius-md: 0.5rem /* 8px */
--radius-lg: 0.75rem /* 12px */
--radius-xl: 1rem /* 16px */
Компоненты¶
UI Primitives¶
Button¶
Варианты:
- primary - meadow-green-500, белый текст (главные CTA)
- secondary - stone-200, тёмный текст
- ghost - прозрачный, hover: stone-100
- glass - glassmorphism эффект
Sizes: sm (32px), md (40px), lg (48px)
Props:
interface ButtonProps {
variant?: 'primary' | 'secondary' | 'ghost' | 'glass';
size?: 'sm' | 'md' | 'lg';
icon?: ReactNode;
loading?: boolean;
disabled?: boolean;
children: ReactNode;
}
Card¶
Варианты:
- solid - белый фон, border stone-200
- glass - glassmorphism (для popups на карте)
- elevated - белый + shadow-lg
Props:
interface CardProps {
variant?: 'solid' | 'glass' | 'elevated';
hoverable?: boolean;
clickable?: boolean;
children: ReactNode;
}
Input¶
Фичи: - Floating label анимация - Real-time валидация с Zod - Иконки слева/справа - Clear button (X)
Props:
interface InputProps {
label?: string;
error?: string;
icon?: ReactNode;
clearable?: boolean;
type?: string;
}
Badge¶
Использование: - Статусы участков: "Доступен" (green), "Забронирован" (amber), "Продан" (red) - Фильтры: "8 соток", "До 500К"
Props:
interface BadgeProps {
color?: 'green' | 'blue' | 'amber' | 'red' | 'stone';
size?: 'sm' | 'md';
children: ReactNode;
}
Domain Components¶
PropertyCard¶
Карточка участка - ключевой компонент, появляется 436+ раз на главной странице.
Дизайн: - Aspect ratio 4:3 для фото - Glassmorphism badge с номером участка - Цена крупно (Geist Mono, semibold) - Скидка badge (amber) если есть original_price - Статус badge внизу справа - Hover: 3D tilt effect + shadow lift
Props:
interface PropertyCardProps {
property: {
id: string;
number: string;
area_sotok: number;
price: number;
original_price?: number;
status: 'available' | 'reserved' | 'sold';
settlement: string;
images: string[];
};
onFavorite?: (id: string) => void;
onClick?: (id: string) => void;
}
YandexMapView¶
Интерактивная карта с 436 участками.
Функционал: - Custom SVG маркеры (3 цвета по статусам) - Кластеризация на zoom < 15 - Glassmorphism popup при клике - Синхронизация с PropertyCard в списке
Props:
interface YandexMapViewProps {
properties: Property[];
selectedProperty?: Property;
onPropertySelect: (property: Property) => void;
filterStatus?: string[];
clusterProperties?: boolean;
}
FilterPanel¶
Панель фильтров для карты участков.
Фильтры: 1. Цена: Range slider (299K - 500K) 2. Площадь: Range slider (8 - 15 соток) 3. Поселок: Checkboxes 4. Статус: Checkboxes
Props:
interface FilterPanelProps {
onFilterChange: (filters: PropertyFilters) => void;
activeFilters: PropertyFilters;
}
interface PropertyFilters {
priceRange: [number, number];
areaRange: [number, number];
settlement: string[];
status: string[];
}
Страницы¶
PropertiesPage (приоритет)¶
Главная страница - интерактивная карта с 436 участками.
Layout Desktop: - FilterPanel (left sidebar, 280px) - YandexMapView (center, 50%) - Property Grid (right, 50%)
Layout Mobile: - Tabs "Карта" / "Список" - Filter chips (horizontal scroll) - Floating action button "Карта"
Функционал: - Map-List синхронизация (click/hover) - Real-time фильтрация (debounced 500ms) - Infinite scroll / pagination - Stagger animation для карточек
HousesPage¶
Каталог 9 типов домов.
Layout: - Grid 3x3 (responsive: 3 → 2 → 1 колонка) - Filter tabs: Все | Шале | Барнхаус | Хай-тек - House Detail Modal с планировкой
AvitoAdsPage / CianAdsPage¶
Управление объявлениями.
Функционал: - Таблица объявлений (сортировка, фильтры) - Create Ad Wizard (3 шага) - AI генерация описаний - Статистика (просмотры, обращения)
LeadsPage¶
CRM дашборд лидов.
Функционал: - Kanban board (drag-and-drop) - Lead detail drawer - AI recommendations - Фильтры по источнику/статусу
API Integration¶
Backend endpoints¶
Properties¶
GET /properties?filters
GET /properties/{id}
POST /properties
PATCH /properties/{id}
DELETE /properties/{id}
Map¶
GET /map/properties # GeoJSON все участки
GET /map/clusters?zoom=X # Кластеризация
GET /map/geocode # Геокодинг адресов
Houses¶
Leads¶
React Query hooks¶
useProperties¶
const { data, isLoading } = useProperties(filters);
// Возвращает: { items: Property[], total: number }
useProperty¶
useUpdateProperty¶
Анимации и микровзаимодействия¶
Framer Motion variants¶
// lib/animations.ts
export const fadeIn = {
initial: { opacity: 0, y: 20 },
animate: { opacity: 1, y: 0 },
transition: { duration: 0.3 }
};
export const staggerChildren = {
animate: {
transition: { staggerChildren: 0.1 }
}
};
Ключевые анимации¶
- Button hover - scale(1.02) + shadow lift
- Card hover - 3D tilt effect
- Filter animation - stagger для карточек
- Map pin pulse - для новых лидов
- Toast notifications - slide in from top
Performance оптимизации¶
Code splitting¶
// Route-based splitting
const PropertiesPage = lazy(() => import('./pages/PropertiesPage'));
const HousesPage = lazy(() => import('./pages/HousesPage'));
Image optimization¶
React Query caching¶
staleTime: 5 * 60 * 1000, // 5 минут
cacheTime: 10 * 60 * 1000, // 10 минут
refetchOnWindowFocus: false,
keepPreviousData: true
Bundle size targets¶
Development¶
Запуск dev сервера¶
Build production¶
Lint¶
Type checking¶
Деплой¶
Vercel¶
Environment variables¶
Тестирование¶
Manual smoke testing¶
- PropertiesPage - карта, фильтры, карточки
- HousesPage - grid, carousel, modal
- Performance - Lighthouse > 90
- Responsive - 375px, 768px, 1280px
- Cross-browser - Chrome, Safari, Firefox
Acceptance criteria¶
✅ Фронтенд запускается без ошибок ✅ Все 436 участков на карте с кластеризацией ✅ Фильтры работают real-time (debounced 500ms) ✅ Map-List синхронизация (click/hover) ✅ PropertyCard анимации smooth ✅ Mobile версия функциональна ✅ Glassmorphism эффекты рендерятся ✅ Шрифты Geist/Inter загружаются ✅ API интеграция с backend ✅ Build production без ошибок
Полезные ссылки¶
Документация¶
Шрифты¶
Референсы дизайна¶
- Airbnb - map + listings sync
- Zillow - real estate UX
- Apple - minimalism
- Figma - glassmorphism
Changelog¶
2026-02-16¶
- Инициализация проекта Vite + React + TypeScript
- Установка всех зависимостей
- Создание документации
- Подготовка к настройке TailwindCSS
Статус: В разработке Приоритет: PropertiesPage (карта участков) Сроки: 14 дней Команда: Solo developer + Claude Code