Законченный MVP

This commit is contained in:
sbb45
2026-05-28 21:03:35 +05:00
parent a566bab1ae
commit 55583e2101
30 changed files with 1883 additions and 143 deletions
+298 -24
View File
@@ -1,42 +1,316 @@
# sv
# Flamy Trade — Frontend
Everything you need to build a Svelte project, powered by [`sv`](https://github.com/sveltejs/cli).
Публичный лендинг и дашборд ML-прогнозов для крипторынка. Построен на **SvelteKit 5** (Runes API), **Tailwind v4**, **TypeScript** и **lightweight-charts v5**.
## Creating a project
---
If you're seeing this, you've probably already done this step. Congrats!
## Стек
```sh
# create a new project
npx sv create my-app
| Слой | Технология |
|---|---|
| Фреймворк | SvelteKit 5 (runes, SSR) |
| Язык | TypeScript (strict) |
| Стили | Tailwind CSS v4 (Vite plugin, `@theme`) |
| Графики | lightweight-charts v5 (TradingView) |
| Сервер | `@sveltejs/adapter-node` (Node.js) |
| Пакетный менеджер | pnpm |
---
## Быстрый старт
**Требования:** Node.js ≥ 20, pnpm ≥ 9
```bash
# 1. Установить зависимости
pnpm install
# 2. Запустить dev-сервер
pnpm dev
# 3. Открыть в браузере
# http://localhost:5173
```
To recreate this project with the same configuration:
Остальные команды:
```sh
# recreate this project
pnpm dlx sv@0.15.3 create --template minimal --types ts --add prettier eslint tailwindcss="plugins:none" sveltekit-adapter="adapter:node" --install pnpm Flamy-Trade_svelte
```bash
pnpm build # Сборка для продакшена (папка build/)
pnpm preview # Превью продакшен-сборки
pnpm check # Svelte + TypeScript проверка типов
pnpm lint # ESLint + Prettier проверка
pnpm format # Автоформатирование
```
## Developing
---
Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
## Структура проекта
```sh
npm run dev
# or start the server and open the app in a new browser tab
npm run dev -- --open
```
src/
├── lib/
│ ├── components/
│ │ ├── Chart.svelte # lightweight-charts обёртка
│ │ ├── home/
│ │ │ ├── DashboardMockup.svelte # 3D-макет на главной
│ │ │ └── DashboardStatus.svelte
│ │ ├── layout/
│ │ │ ├── Header.svelte # Фиксированная шапка + мобильное меню
│ │ │ └── Footer.svelte
│ │ └── ui/
│ │ ├── Button.svelte # Универсальная кнопка/ссылка
│ │ └── Logo.svelte
│ ├── blog/
│ │ └── posts.ts # Статьи блога (статические данные)
│ ├── stores/
│ │ └── chartStore.ts # Типы + генератор фейковых данных
│ ├── utils.ts # cn() — утилита для className
│ └── index.ts
├── routes/
│ ├── +layout.svelte # Корневой layout: Header, Footer, шрифты
│ ├── +page.svelte # Главная страница (секции)
│ ├── +error.svelte # Страница ошибки
│ ├── (sections)/ # Секции главной страницы
│ │ ├── Hero.svelte
│ │ ├── Ticker.svelte
│ │ ├── About.svelte
│ │ ├── Features.svelte
│ │ ├── Stats.svelte
│ │ ├── BlogPreview.svelte
│ │ └── Cta.svelte
│ ├── about/
│ │ ├── +page.svelte
│ │ └── _data.ts
│ ├── blog/
│ │ ├── +page.svelte # Список статей
│ │ └── [slug]/
│ │ ├── +page.ts # Загрузка статьи по slug
│ │ └── +page.svelte # Статья
│ └── dashboard/
│ └── +page.svelte # Интерактивный дашборд с графиком
└── routes/layout.css # Tailwind @theme + глобальные стили
```
## Building
---
To create a production version of your app:
## Дизайн-система
```sh
npm run build
### Цвета (`layout.css`)
```css
--color-primary: #fe4b07 /* Акцент — оранжевый */
--color-primary-h:#c83e06 /* Hover-состояние */
--color-bg: #09080a /* Фон страницы */
--color-bg-e: #0f0e10 /* Elevated (шапка, карточки) */
--color-bg-c: #141318 /* Card background */
--color-bg-h: #1a191e /* Hover / бордеры */
--color-title: #f0ede6 /* Основной текст */
--color-desc: #8a887f /* Вторичный текст */
```
You can preview the production build with `npm run preview`.
В Tailwind используются как `bg-primary`, `text-desc`, `border-bg-h` и т.д.
> To deploy your app, you may need to install an [adapter](https://svelte.dev/docs/kit/adapters) for your target environment.
### Шрифты
| Переменная | Семейство | Применение |
|---|---|---|
| `font-display` | Unbounded | Заголовки, кнопки, тикеры |
| `font-sans` | DM Sans | Основной текст |
| `font-mono` | JetBrains Mono | Цены, метки, метаданные |
Подключаются через Google Fonts в `+layout.svelte`.
### Компонент `Button.svelte`
```svelte
<!-- Первичная (ссылка) -->
<Button href="/dashboard">Открыть дашборд</Button>
<!-- Вторичная (кнопка) -->
<Button variant="secondary" onclick={handler}>Действие</Button>
```
Props: `href?`, `target?`, `variant?: 'primary' | 'secondary'`, `class?`
---
## Дашборд и Charts
### Архитектура данных
```
chartStore.ts → generateChartData(symbolId, timeframeId)
└── возвращает ChartData
├── candles: CandleBar[] // 160 свечей
├── prediction: PredPoint[] // 19 прогнозных точек
├── signal: Signal // direction, confidence, entry/tp/sl
├── currentPrice: number
└── change24h(Pct): number
```
`generateChartData`**заглушка с детерминированными фейковыми данными**. При подключении реального бекенда её нужно заменить на API-запрос, сохранив возвращаемые типы:
```typescript
// chartStore.ts — заменить эту функцию на реальный запрос:
export async function fetchChartData(symbolId: string, tfId: TimeframeId): Promise<ChartData> {
const res = await fetch(`/api/chart/${symbolId}?tf=${tfId}`);
return res.json();
}
```
### Компонент `Chart.svelte`
```svelte
<Chart data={chartData} decimals={2} height={520} />
```
| Prop | Тип | Описание |
|---|---|---|
| `data` | `ChartData` | Свечи + прогноз + сигнал |
| `decimals` | `number` | Кол-во знаков после запятой для цены |
| `height` | `number` | Высота canvas в пикселях (default: 520) |
Что рендерится:
- **CandlestickSeries** — исторические зелёные/красные свечи
- **LineSeries** — пунктирная оранжевая линия ML-прогноза (19 свечей вперёд)
- **PriceLine** × 3 — горизонтальные линии Entry / TP / SL с подписями на шкале
- **OHLC тултип** — кастомный HTML-оверлей при наведении (показывает O/H/L/C и ML-значение)
- **ResizeObserver** — автоматически подстраивает ширину и высоту при изменении окна
### Таймфреймы и символы
Определены в `chartStore.ts`:
```typescript
SYMBOLS // 8 монет: BTC ETH SOL BNB XRP ADA DOGE LINK
TIMEFRAMES // 6 таймфреймов: 1m 5m 15m 1h 4h 1d
```
---
## Контракт API (для бекенда)
Дашборд ожидает от бекенда следующую форму ответа:
```typescript
type ChartData = {
candles: Array<{
time: number; // Unix timestamp (UTC seconds)
open: number;
high: number;
low: number;
close: number;
}>;
prediction: Array<{
time: number; // Unix timestamp будущих свечей
value: number; // Прогнозная цена (mid/close)
}>;
signal: {
direction: 'long' | 'short';
confidence: number; // 0100
entry: number;
tp: number;
sl: number;
};
currentPrice: number;
change24h: number;
change24hPct: number;
};
```
Эндпоинт (предполагаемый):
```
GET /api/chart/:symbol?tf=5m
```
---
## Блог
Статьи хранятся в `src/lib/blog/posts.ts` как статический массив `Post[]`.
```typescript
type Post = {
id: number;
slug: string; // URL: /blog/:slug
date: string; // ISO 8601
title: string;
description: string;
tags: string[];
content: string; // HTML-строка
};
```
Для подключения CMS — заменить `posts` на API-запрос в `+page.ts` / `+page.server.ts`.
---
## Конфигурация
### SvelteKit (`svelte.config.js`)
- Адаптер: `adapter-node` (деплой как Node.js-сервер)
- Runes: принудительно включены для всех файлов вне `node_modules`
### Tailwind v4 (`layout.css`)
Tailwind подключается через Vite-плагин (`@tailwindcss/vite`), конфиг CSS-первый — все кастомные токены в блоке `@theme` в `src/routes/layout.css`.
**Добавить новый токен:**
```css
/* layout.css */
@theme {
--color-accent: #your-color;
}
```
После этого доступен как `bg-accent`, `text-accent` и т.д.
---
## Деплой
Сборка производит Node.js-сервер:
```bash
pnpm build
node build/index.js
```
Переменные окружения:
```
PORT=3000 # порт (default: 3000)
HOST=0.0.0.0 # хост
ORIGIN=https://... # обязательно при deploy за проксей
```
Docker (минимальный `Dockerfile`):
```dockerfile
FROM node:22-alpine
WORKDIR /app
COPY build/ ./build/
COPY package.json .
RUN npm install --omit=dev --ignore-scripts
CMD ["node", "build/index.js"]
```
---
## Соглашения по коду
- **Svelte 5 Runes** везде: `$state`, `$derived`, `$effect`, `$props` — никакого legacy API
- **Нет `export let`** — только деструктуризация `$props()`
- **Tailwind-first** — inline-стили только там, где Tailwind не справляется (динамические значения, chart dimensions)
- **cn()** из `$lib/utils` для условного объединения классов
- **Нет комментариев** если смысл очевиден из имён; комментарий — только для неочевидного инварианта
- **SSR-safe** — всё что требует `window`/`document` — только в `onMount`
- **Cleanup** — каждый `onMount` возвращает функцию очистки (removeEventListener, disconnect, remove)
---
## Известные ограничения
- Данные в дашборде — **фейковые** (детерминированный генератор). Требует подключения реального API бекенда через замену `generateChartData` в `chartStore.ts`
- Прогнозная линия — условная визуализация; реальная модель возвращает `prediction[]` из бекенда
- Блог — статические данные в коде; для production рекомендуется CMS или headless API