From 55583e2101501f96fff079e8ee9430603cdc579a Mon Sep 17 00:00:00 2001 From: sbb45 Date: Thu, 28 May 2026 21:03:35 +0500 Subject: [PATCH] =?UTF-8?q?=D0=97=D0=B0=D0=BA=D0=BE=D0=BD=D1=87=D0=B5?= =?UTF-8?q?=D0=BD=D0=BD=D1=8B=D0=B9=20MVP?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 322 ++++++++++++++++-- package.json | 2 + pnpm-lock.yaml | 23 ++ src/lib/blog/posts.ts | 66 ++++ src/lib/components/Chart.svelte | 246 +++++++++++++ .../{ => home}/DashboardMockup.svelte | 2 +- .../{ => home}/DashboardStatus.svelte | 0 src/lib/components/layout/Footer.svelte | 4 +- src/lib/components/layout/Header.svelte | 28 +- src/lib/components/ui/Button.svelte | 6 +- src/lib/gsap/actions.ts | 168 +++++++++ src/lib/stores/chartStore.ts | 141 ++++++++ .../{_sections => (sections)}/About.svelte | 33 +- .../BlogPreview.svelte | 19 +- src/routes/(sections)/Cta.svelte | 79 +++++ .../{_sections => (sections)}/Features.svelte | 17 +- src/routes/(sections)/Hero.svelte | 77 +++++ .../{_sections => (sections)}/Stats.svelte | 23 +- .../{_sections => (sections)}/Ticker.svelte | 0 src/routes/+layout.svelte | 1 + src/routes/+page.svelte | 15 +- src/routes/_sections/Cta.svelte | 29 -- src/routes/_sections/Hero.svelte | 38 --- src/routes/about/+page.svelte | 106 ++++++ src/routes/about/_data.ts | 55 +++ src/routes/blog/+page.svelte | 115 +++++++ src/routes/blog/[slug]/+page.svelte | 200 +++++++++++ src/routes/blog/[slug]/+page.ts | 9 + src/routes/dashboard/+page.svelte | 196 +++++++++++ src/routes/layout.css | 6 +- 30 files changed, 1883 insertions(+), 143 deletions(-) create mode 100644 src/lib/blog/posts.ts create mode 100644 src/lib/components/Chart.svelte rename src/lib/components/{ => home}/DashboardMockup.svelte (98%) rename src/lib/components/{ => home}/DashboardStatus.svelte (100%) create mode 100644 src/lib/gsap/actions.ts create mode 100644 src/lib/stores/chartStore.ts rename src/routes/{_sections => (sections)}/About.svelte (52%) rename src/routes/{_sections => (sections)}/BlogPreview.svelte (71%) create mode 100644 src/routes/(sections)/Cta.svelte rename src/routes/{_sections => (sections)}/Features.svelte (85%) create mode 100644 src/routes/(sections)/Hero.svelte rename src/routes/{_sections => (sections)}/Stats.svelte (53%) rename src/routes/{_sections => (sections)}/Ticker.svelte (100%) delete mode 100644 src/routes/_sections/Cta.svelte delete mode 100644 src/routes/_sections/Hero.svelte create mode 100644 src/routes/about/+page.svelte create mode 100644 src/routes/about/_data.ts create mode 100644 src/routes/blog/+page.svelte create mode 100644 src/routes/blog/[slug]/+page.svelte create mode 100644 src/routes/blog/[slug]/+page.ts create mode 100644 src/routes/dashboard/+page.svelte diff --git a/README.md b/README.md index 4d5f3b6..65a1552 100644 --- a/README.md +++ b/README.md @@ -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 + + + + + +``` + +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 { + const res = await fetch(`/api/chart/${symbolId}?tf=${tfId}`); + return res.json(); +} +``` + +### Компонент `Chart.svelte` + +```svelte + +``` + +| 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; // 0–100 + 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 diff --git a/package.json b/package.json index 2773e9e..12d7bf0 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,8 @@ }, "dependencies": { "clsx": "^2.1.1", + "gsap": "^3.15.0", + "lightweight-charts": "^5.2.0", "tailwind-merge": "^3.6.0" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ccd7d4d..c5e0f1a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,6 +11,12 @@ importers: clsx: specifier: ^2.1.1 version: 2.1.1 + gsap: + specifier: ^3.15.0 + version: 3.15.0 + lightweight-charts: + specifier: ^5.2.0 + version: 5.2.0 tailwind-merge: specifier: ^3.6.0 version: 3.6.0 @@ -820,6 +826,9 @@ packages: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} + fancy-canvas@2.1.0: + resolution: {integrity: sha512-nifxXJ95JNLFR2NgRV4/MxVP45G9909wJTEKz5fg/TZS20JJZA6hfgRVh/bC9bwl2zBtBNcYPjiBE4njQHVBwQ==} + fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} @@ -876,6 +885,9 @@ packages: graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + gsap@3.15.0: + resolution: {integrity: sha512-dMW4CWBTUK1AEEDeZc1g4xpPGIrSf9fJF960qbTZmN/QwZIWY5wgliS6JWl9/25fpTGJrMRtSjGtOmPnfjZB+A==} + hasown@2.0.3: resolution: {integrity: sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==} engines: {node: '>= 0.4'} @@ -1013,6 +1025,9 @@ packages: resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} engines: {node: '>= 12.0.0'} + lightweight-charts@5.2.0: + resolution: {integrity: sha512-ey3Vas8UhV06ni+LT9TA1nEe4y8So4Mi6CL/oarNHFMyTktz/xy8e8+oh04Q//eO3t6etvFXgayz2fClyFQb5w==} + lilconfig@2.1.0: resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} engines: {node: '>=10'} @@ -2048,6 +2063,8 @@ snapshots: esutils@2.0.3: {} + fancy-canvas@2.1.0: {} + fast-deep-equal@3.1.3: {} fast-json-stable-stringify@2.1.0: {} @@ -2089,6 +2106,8 @@ snapshots: graceful-fs@4.2.11: {} + gsap@3.15.0: {} + hasown@2.0.3: dependencies: function-bind: 1.1.2 @@ -2191,6 +2210,10 @@ snapshots: lightningcss-win32-arm64-msvc: 1.32.0 lightningcss-win32-x64-msvc: 1.32.0 + lightweight-charts@5.2.0: + dependencies: + fancy-canvas: 2.1.0 + lilconfig@2.1.0: {} locate-character@3.0.0: {} diff --git a/src/lib/blog/posts.ts b/src/lib/blog/posts.ts new file mode 100644 index 0000000..50fc447 --- /dev/null +++ b/src/lib/blog/posts.ts @@ -0,0 +1,66 @@ +export type Post = { + id: number; + slug: string; + date: string; + title: string; + description: string; + tags: string[]; + content: string; +}; + +export const posts: Post[] = [ + { + id: 1, + slug: 'osnovy-upravleniya-riskami', + date: '2026-05-18', + title: 'Основы управления рисками', + description: + 'Как использовать уровни Stop Loss и Take Profit для грамотного управления капиталом при работе с прогнозами.', + tags: ['RISK', 'TRADING', 'EDUCATION'], + content: ` +

Управление рисками — фундамент любой торговой стратегии. Без него даже точный ML-прогноз не поможет сохранить капитал.

+

Stop Loss: где ваша позиция неправа

+

Stop Loss — уровень, при достижении которого позиция закрывается автоматически. Это не признание ошибки, а часть стратегии. На графиках Flamy AI уровень SL рассчитывается моделью на основе исторической волатильности инструмента.

+

Take Profit: когда забирать прибыль

+

Take Profit — целевой уровень закрытия позиции с прибылью. TP рассчитывается пропорционально прогнозному движению с учётом Risk:Reward ratio.

+

Risk:Reward Ratio

+

Оптимальное соотношение риска к доходности — не менее 1:2. Это означает, что потенциальная прибыль должна минимум вдвое превышать риск.

+
    +
  • SL: не более 1% от капитала на сделку
  • +
  • TP: 2% и выше от точки входа
  • +
  • Одна сделка: не более 2% депозита
  • +
+

Почему это важно при работе с ML-прогнозами

+

ML-модель не даёт гарантий. Уверенность 80% означает, что 20% прогнозов будут неточными. Управление рисками — страховка на эти 20%.

+ ` + }, + { + id: 2, + slug: 'kak-chitat-grafiki-flamy-ai', + date: '2026-05-17', + title: 'Как читать графики Flamy AI', + description: + 'Краткое объяснение свечей, прогнозной зоны, TP и SL на графиках Flamy AI.', + tags: ['ML', 'FORECAST', 'CHARTS'], + content: ` +

Графики Flamy AI содержат три слоя: исторические свечи, прогнозную зону и уровни торгового плана. Разберём каждый из них.

+

Исторические свечи

+

Левая часть графика — реальные OHLC-свечи. Зелёные — бычьи (close > open), красные — медвежьи. Это основа для анализа модели.

+

Прогнозная зона

+

Правая часть — прогнозные свечи на горизонт 19 периодов вперёд. Это не точные значения, а вероятностный коридор движения цены на ближайшие 95 минут.

+

Уровни Entry, TP и SL

+

Если модель публикует режим TRADE_PLAN, на графике появляются три горизонтальные линии:

+
    +
  • Entry — рекомендуемый уровень входа в позицию
  • +
  • TP — цель Take Profit
  • +
  • SL — Stop Loss для ограничения убытков
  • +
+

Таймфрейм и горизонт

+

Все графики работают на таймфрейме 5 минут. Горизонт прогноза — 19 свечей = 95 минут вперёд. Прогнозы обновляются каждый час автоматически.

+ ` + } +]; + +export function getPostBySlug(slug: string): Post | undefined { + return posts.find((p) => p.slug === slug); +} \ No newline at end of file diff --git a/src/lib/components/Chart.svelte b/src/lib/components/Chart.svelte new file mode 100644 index 0000000..7ff514e --- /dev/null +++ b/src/lib/components/Chart.svelte @@ -0,0 +1,246 @@ + + +
+ {#if tip.visible} + {@const maxX = container?.clientWidth ?? 500} + {@const left = tip.x + 160 > maxX ? tip.x - 168 : tip.x + 14} + {@const top = Math.max(tip.y - 90, 8)} +
+

{tip.time}

+ {#each [['O', tip.open], ['H', tip.high], ['L', tip.low], ['C', tip.close]] as [lbl, val]} +
+ {lbl} + {fmt(val as number)} +
+ {/each} + {#if tip.pred !== undefined} +
+ ML + {fmt(tip.pred)} +
+ {/if} +
+ {/if} +
diff --git a/src/lib/components/DashboardMockup.svelte b/src/lib/components/home/DashboardMockup.svelte similarity index 98% rename from src/lib/components/DashboardMockup.svelte rename to src/lib/components/home/DashboardMockup.svelte index c6c8964..7e9d9e8 100644 --- a/src/lib/components/DashboardMockup.svelte +++ b/src/lib/components/home/DashboardMockup.svelte @@ -62,7 +62,7 @@ } -
+
-
+

@@ -34,7 +34,7 @@ {/each}

-
+
Дисклеймер

Материалы являются результатом работы исследовательской ML-модели и используются в diff --git a/src/lib/components/layout/Header.svelte b/src/lib/components/layout/Header.svelte index 03f7a0a..23a6314 100644 --- a/src/lib/components/layout/Header.svelte +++ b/src/lib/components/layout/Header.svelte @@ -1,22 +1,35 @@ -

-
+
+
- - + +
+ +
- +
+ +
- -
diff --git a/src/routes/_sections/BlogPreview.svelte b/src/routes/(sections)/BlogPreview.svelte similarity index 71% rename from src/routes/_sections/BlogPreview.svelte rename to src/routes/(sections)/BlogPreview.svelte index 0300821..88d91bb 100644 --- a/src/routes/_sections/BlogPreview.svelte +++ b/src/routes/(sections)/BlogPreview.svelte @@ -1,4 +1,6 @@ + +
+
+
+

+ ОТКРОЙТЕ
ДАШБОРД +

+
+ +
+

+ Материалы носят исследовательский характер.
Не являются инвестиционными рекомендациями. +

+
+
+ +
+
+
diff --git a/src/routes/_sections/Features.svelte b/src/routes/(sections)/Features.svelte similarity index 85% rename from src/routes/_sections/Features.svelte rename to src/routes/(sections)/Features.svelte index 65646df..ef85407 100644 --- a/src/routes/_sections/Features.svelte +++ b/src/routes/(sections)/Features.svelte @@ -1,4 +1,6 @@ + +
+
+

+ Рыночный + прогноз + от ML-модели +

+ +

+ Исторические свечи, прогнозная зона, уровни входа и выхода — всё на одном интерактивном + графике. Горизонт 19 свечей, таймфрейм 5M. +

+ +
+ + +
+
+ +
+ +
+ + + + + +
diff --git a/src/routes/_sections/Stats.svelte b/src/routes/(sections)/Stats.svelte similarity index 53% rename from src/routes/_sections/Stats.svelte rename to src/routes/(sections)/Stats.svelte index 65eb99a..28eb737 100644 --- a/src/routes/_sections/Stats.svelte +++ b/src/routes/(sections)/Stats.svelte @@ -1,4 +1,6 @@ -
-
-
+
+
{#each stats as stat, i (stat.num)}
0 ? 'border-t sm:border-t-0 sm:border-l' : ''}" >
{stat.num} {#if stat.suffix} {stat.suffix} {/if}
- + {stat.label} - {stat.sub} + {stat.sub}
diff --git a/src/routes/_sections/Ticker.svelte b/src/routes/(sections)/Ticker.svelte similarity index 100% rename from src/routes/_sections/Ticker.svelte rename to src/routes/(sections)/Ticker.svelte diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 11a3483..73a8fa1 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -17,6 +17,7 @@ +
{@render children()}