diff --git a/app/landing/page.js b/app/landing/page.js
new file mode 100644
index 0000000..b1c9b4e
--- /dev/null
+++ b/app/landing/page.js
@@ -0,0 +1,173 @@
+import Link from 'next/link';
+import { Sparkles, Zap, Calendar, BarChart3, MessageCircle, Globe, ArrowRight, Check } from 'lucide-react';
+
+const FEATURES = [
+ { icon: Zap, title: 'AI генерация постов', desc: 'Claude пишет посты под твою нишу и стиль. Тексты, которые хочется читать.' },
+ { icon: Calendar, title: 'Отложенная публикация', desc: 'Планируй контент на неделю вперёд. Автопостинг в нужное время.' },
+ { icon: Globe, title: 'Telegram, VK, MAX', desc: 'Один интерфейс для всех платформ. Публикуй везде одновременно.' },
+ { icon: Sparkles, title: 'Авто-черновики', desc: 'Каждое утро 3 новых поста на проверку. Ты только одобряешь лучшее.' },
+ { icon: BarChart3, title: 'Аналитика канала', desc: 'Видишь что работает. Охват, реакции, лучшее время для публикации.' },
+ { icon: MessageCircle, title: 'Inbox и AI-ответы', desc: 'Комментарии приходят в одно место. AI предлагает ответы за тебя.' },
+];
+
+const PLANS = [
+ {
+ name: 'Free', price: 0, credits: 50, channels: 1,
+ features: ['1 канал', '50 кредитов/мес', 'AI генерация постов', 'Планировщик'],
+ cta: 'Начать бесплатно', ctaHref: '/register', accent: false,
+ },
+ {
+ name: 'Starter', price: 490, credits: 500, channels: 2,
+ features: ['2 канала', '500 кредитов/мес', 'Авто-черновики', 'Аналитика', 'Inbox'],
+ cta: 'Попробовать', ctaHref: '/register', accent: true,
+ },
+ {
+ name: 'Pro', price: 1490, credits: 2000, channels: 5,
+ features: ['5 каналов', '2000 кредитов/мес', 'Все платформы', 'Хештеги AI', 'Опросы TG'],
+ cta: 'Выбрать Pro', ctaHref: '/register', accent: false,
+ },
+ {
+ name: 'Business', price: 3990, credits: -1, channels: -1,
+ features: ['Безлимит каналов', 'Безлимит кредитов', 'Приоритетная поддержка', 'API доступ'],
+ cta: 'Связаться', ctaHref: 'mailto:hello@zeropost.ru', accent: false,
+ },
+];
+
+export default function LandingPage() {
+ return (
+
+ {/* Nav */}
+
+
+ {/* Hero */}
+
+
+ AI-контент для Telegram и VK
+
+
+ Ведите канал на автопилоте.
+ AI пишет, ты одобряешь.
+
+
+ ZeroPost генерирует посты для Telegram и VK, планирует публикации и отвечает на комментарии.
+ Тратьте 10 минут в день вместо 2 часов.
+
+
+
+ Начать бесплатно
+
+
+ Уже есть аккаунт
+
+
+ 50 кредитов бесплатно · Без карты
+
+
+ {/* Features */}
+
+ Что умеет ZeroPost
+
+ {FEATURES.map(f => (
+
+
+
{f.title}
+
{f.desc}
+
+ ))}
+
+
+
+ {/* How it works */}
+
+ Как это работает
+
+ {[
+ { step: '1', title: 'Добавь канал', desc: 'Подключи Telegram, VK или MAX. Укажи нишу и стиль.' },
+ { step: '2', title: 'AI генерирует', desc: 'Каждое утро — свежие черновики. Редактируй, одобряй.' },
+ { step: '3', title: 'Публикуй в один клик', desc: 'Запланируй или публикуй сейчас. Всё само.' },
+ ].map(s => (
+
+
+ {s.step}
+
+
{s.title}
+
{s.desc}
+
+ ))}
+
+
+
+ {/* Pricing */}
+
+ Тарифы
+ Начни бесплатно, масштабируй по мере роста
+
+ {PLANS.map(plan => (
+
+ {plan.accent && (
+
✨ Популярный
+ )}
+
{plan.name}
+
+ {plan.price === 0 ? 0₽ : `${plan.price}₽`}
+ {plan.price > 0 && /мес}
+
+
+ {plan.credits === -1 ? '∞ кредитов' : `${plan.credits} кредитов/мес`}
+
+
+ {plan.features.map(f => (
+ -
+ {f}
+
+ ))}
+
+
+ {plan.cta}
+
+
+ ))}
+
+
+
+ {/* CTA */}
+
+ Готовы попробовать?
+ 50 бесплатных кредитов. Без карты. Настройка за 5 минут.
+
+ Создать аккаунт
+
+
+
+ {/* Footer */}
+
+
+ );
+}
diff --git a/app/page.js b/app/page.js
index 8e4d152..22bf152 100644
--- a/app/page.js
+++ b/app/page.js
@@ -15,7 +15,7 @@ const GOAL_LABELS = {
export default async function HomePage() {
const user = await requireUser();
- if (!user) redirect('/login');
+ if (!user) redirect('/landing');
let channels = [];
try {
@@ -43,50 +43,47 @@ export default async function HomePage() {
{channels.length === 0 ? (
-
-
-
-
Пока пусто
-
- Создай первый канал, чтобы начать генерировать посты
-
+
+
Нет каналов
+
Добавь первый канал чтобы начать генерировать контент
- Создать канал
+ Создать первый канал
) : (
-
+
{channels.map(ch => (
-
+
-
- {ch.name}
-
-
- {(ch.goal || '').split(',').map(g => GOAL_LABELS[g.trim()] || g.trim()).join(' · ')}
+
+
{ch.name}
+ {ch.tg_username && (
+ @{ch.tg_username}
+ )}
+
+
+ {ch.platform || 'telegram'}
{ch.niche && (
-
- {ch.niche}
-
+
{ch.niche}
)}
-
- {ch.audience && (
+
+ {ch.goal && (
-
- Есть ЦА
+
+ {GOAL_LABELS[ch.goal] || ch.goal}
)}
- {ch.style?.example_posts?.length > 0 && (
+ {ch.language && (
-
- {ch.style.example_posts.length} пример{ch.style.example_posts.length === 1 ? '' : 'а'}
+
+ {ch.language.toUpperCase()}
)}
diff --git a/app/register/page.js b/app/register/page.js
new file mode 100644
index 0000000..bad3c16
--- /dev/null
+++ b/app/register/page.js
@@ -0,0 +1,121 @@
+'use client';
+import { useState } from 'react';
+import { useRouter } from 'next/navigation';
+import Link from 'next/link';
+import { Loader2, Eye, EyeOff, Sparkles } from 'lucide-react';
+
+export default function RegisterPage() {
+ const router = useRouter();
+ const [email, setEmail] = useState('');
+ const [pass, setPass] = useState('');
+ const [pass2, setPass2] = useState('');
+ const [name, setName] = useState('');
+ const [show, setShow] = useState(false);
+ const [busy, setBusy] = useState(false);
+ const [error, setError] = useState('');
+
+ async function submit() {
+ if (!email.trim() || !pass) { setError('Заполните email и пароль'); return; }
+ if (pass.length < 6) { setError('Пароль минимум 6 символов'); return; }
+ if (pass !== pass2) { setError('Пароли не совпадают'); return; }
+ setBusy(true); setError('');
+ try {
+ const res = await fetch('/api/auth/login', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ email: email.trim(), password: pass, name: name.trim() || undefined, mode: 'register' }),
+ }).then(r => r.json());
+ if (!res.ok) { setError(res.error || 'Ошибка'); setBusy(false); return; }
+ router.push(res.isNew ? '/onboarding' : '/');
+ } catch { setError('Ошибка соединения'); setBusy(false); }
+ }
+
+ return (
+
+ {/* Background glow */}
+
+
+
+ {/* Logo */}
+
+
+
+ ZeroPost
+
+
Создайте аккаунт — это бесплатно
+
+
+
+
Регистрация
+
+
+
+ setName(e.target.value)}
+ placeholder="Алексей"
+ className="input w-full" autoFocus />
+
+
+
+
+ setEmail(e.target.value)}
+ onKeyDown={e => e.key === 'Enter' && submit()}
+ placeholder="you@example.com"
+ className="input w-full" />
+
+
+
+
+
+ setPass(e.target.value)}
+ placeholder="Минимум 6 символов"
+ className="input w-full pr-10" />
+
+
+
+
+
+
+ setPass2(e.target.value)}
+ onKeyDown={e => e.key === 'Enter' && submit()}
+ placeholder="Ещё раз"
+ className="input w-full" />
+
+
+ {error &&
{error}
}
+
+
+
+
+
+
+ Уже есть аккаунт? Войти →
+
+
+
+ {/* Бонус */}
+
+ 🎁 При регистрации — 50 бесплатных кредитов
+
+
+
+ Регистрируясь, вы принимаете{' '}
+ условия использования
+
+
+
+ );
+}
diff --git a/components/Header.js b/components/Header.js
index c43411f..ff58c54 100644
--- a/components/Header.js
+++ b/components/Header.js
@@ -2,7 +2,7 @@
import Link from 'next/link';
import { useRouter } from 'next/navigation';
import { useEffect, useState } from 'react';
-import { Sparkles, LogOut, CalendarDays, Coins, FileText } from 'lucide-react';
+import { Sparkles, LogOut, CalendarDays, Coins, FileText, Settings2 } from 'lucide-react';
import ThemeToggle from './ThemeToggle';
export default function Header({ user }) {
@@ -63,3 +63,21 @@ export default function Header({ user }) {
);
}
+
+// Публичный хедер для лендинга — отдельный экспорт
+export function PublicHeader() {
+ return (
+
+ );
+}