first commit
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
|
||||
export const runtime = "nodejs";
|
||||
|
||||
const MAX_LENGTHS = {
|
||||
name: 100,
|
||||
contact: 150,
|
||||
message: 2000,
|
||||
};
|
||||
|
||||
// Убираем HTML-теги и обрезаем длину, чтобы нельзя было сломать
|
||||
// форматирование сообщения в Telegram или протащить лишний код.
|
||||
function sanitize(value: unknown, maxLength: number): string {
|
||||
if (typeof value !== "string") return "";
|
||||
return value.replace(/<[^>]*>/g, "").trim().slice(0, maxLength);
|
||||
}
|
||||
|
||||
// Экранируем спецсимволы Telegram MarkdownV2.
|
||||
function escapeMarkdown(text: string): string {
|
||||
return text.replace(/[_*[\]()~`>#+\-=|{}.!\\]/g, (m) => `\\${m}`);
|
||||
}
|
||||
|
||||
export async function POST(req: NextRequest) {
|
||||
const token = process.env.TELEGRAM_BOT_TOKEN;
|
||||
const chatId = process.env.TELEGRAM_CHAT_ID;
|
||||
|
||||
if (!token || !chatId) {
|
||||
console.error("TELEGRAM_BOT_TOKEN или TELEGRAM_CHAT_ID не заданы");
|
||||
return NextResponse.json(
|
||||
{ ok: false, error: "Сервис временно недоступен, попробуйте позже" },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
|
||||
let body: unknown;
|
||||
try {
|
||||
body = await req.json();
|
||||
} catch {
|
||||
return NextResponse.json(
|
||||
{ ok: false, error: "Некорректный запрос" },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
const { name, contact, message } = (body ?? {}) as Record<string, unknown>;
|
||||
|
||||
const cleanName = sanitize(name, MAX_LENGTHS.name);
|
||||
const cleanContact = sanitize(contact, MAX_LENGTHS.contact);
|
||||
const cleanMessage = sanitize(message, MAX_LENGTHS.message);
|
||||
|
||||
if (!cleanName || !cleanContact || !cleanMessage) {
|
||||
return NextResponse.json(
|
||||
{ ok: false, error: "Заполните имя, контакт и сообщение" },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
const text = [
|
||||
"*Новая заявка с сайта LabNetHub*",
|
||||
"",
|
||||
`*Имя:* ${escapeMarkdown(cleanName)}`,
|
||||
`*Контакт:* ${escapeMarkdown(cleanContact)}`,
|
||||
`*Сообщение:*`,
|
||||
escapeMarkdown(cleanMessage),
|
||||
].join("\n");
|
||||
|
||||
try {
|
||||
const telegramRes = await fetch(
|
||||
`https://api.telegram.org/bot${token}/sendMessage`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
chat_id: chatId,
|
||||
text,
|
||||
parse_mode: "MarkdownV2",
|
||||
}),
|
||||
}
|
||||
);
|
||||
|
||||
if (!telegramRes.ok) {
|
||||
const details = await telegramRes.text();
|
||||
console.error("Telegram API error:", details);
|
||||
return NextResponse.json(
|
||||
{ ok: false, error: "Не удалось отправить сообщение" },
|
||||
{ status: 502 }
|
||||
);
|
||||
}
|
||||
|
||||
return NextResponse.json({ ok: true });
|
||||
} catch (err) {
|
||||
console.error("Ошибка отправки в Telegram:", err);
|
||||
return NextResponse.json(
|
||||
{ ok: false, error: "Не удалось отправить сообщение" },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
import type { Metadata } from "next";
|
||||
import Link from "next/link";
|
||||
import {
|
||||
Send,
|
||||
MessageCircle,
|
||||
ArrowUpRight,
|
||||
Check,
|
||||
Bell,
|
||||
ShoppingBag,
|
||||
Headphones,
|
||||
Workflow,
|
||||
Mail,
|
||||
FileText,
|
||||
} from "lucide-react";
|
||||
import PageHero from "@/components/PageHero";
|
||||
import SectionEyebrow from "@/components/SectionEyebrow";
|
||||
import CTASection from "@/components/CTASection";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Боты для Telegram и VK",
|
||||
description:
|
||||
"Разработка Telegram- и VK-ботов любой сложности: автоматизация заявок, уведомления, интеграция с CRM.",
|
||||
};
|
||||
|
||||
const platforms = [
|
||||
{
|
||||
icon: Send,
|
||||
title: "Telegram-боты",
|
||||
description:
|
||||
"Боты любой сложности: приём заявок, уведомления, интеграция с CRM и сервисами.",
|
||||
points: ["Диалоговые сценарии и кнопки", "Оплата и интеграции", "Уведомления в реальном времени"],
|
||||
},
|
||||
{
|
||||
icon: MessageCircle,
|
||||
title: "Боты для ВКонтакте",
|
||||
description:
|
||||
"Боты для сообществ VK: рассылки, магазины в чате, поддержка подписчиков.",
|
||||
points: ["Автоответы и сценарии диалога", "Магазин прямо в сообществе", "Рассылки по базе подписчиков"],
|
||||
},
|
||||
];
|
||||
|
||||
const useCases = [
|
||||
{
|
||||
icon: FileText,
|
||||
title: "Приём заявок",
|
||||
description: "Клиент оставляет заявку в чате — она сразу попадает в CRM или менеджеру.",
|
||||
},
|
||||
{
|
||||
icon: Bell,
|
||||
title: "Уведомления",
|
||||
description: "Автоматические напоминания клиентам и сотрудникам о статусе заказа.",
|
||||
},
|
||||
{
|
||||
icon: ShoppingBag,
|
||||
title: "Магазин в чате",
|
||||
description: "Каталог, корзина и оформление заказа без перехода на сайт.",
|
||||
},
|
||||
{
|
||||
icon: Headphones,
|
||||
title: "Поддержка клиентов",
|
||||
description: "Ответы на частые вопросы и передача сложных случаев менеджеру.",
|
||||
},
|
||||
{
|
||||
icon: Workflow,
|
||||
title: "Интеграция с CRM",
|
||||
description: "Бот пишет и читает данные напрямую из вашей CRM-системы.",
|
||||
},
|
||||
{
|
||||
icon: Mail,
|
||||
title: "Рассылки",
|
||||
description: "Массовые и сегментированные рассылки по базе клиентов.",
|
||||
},
|
||||
];
|
||||
|
||||
export default function BotsPage() {
|
||||
return (
|
||||
<>
|
||||
<PageHero
|
||||
eyebrow="Боты для соцсетей"
|
||||
title="Боты, которые"
|
||||
highlight="работают без выходных"
|
||||
subtitle="Создаём Telegram- и VK-ботов любой сложности: автоматизация заявок, уведомления, интеграция с CRM и сервисами вашего бизнеса."
|
||||
>
|
||||
<Link
|
||||
href="/contacts"
|
||||
className="inline-flex items-center gap-1.5 rounded-full bg-blue-500 px-6 py-3.5 font-medium text-white transition-transform hover:scale-[1.03]"
|
||||
>
|
||||
Обсудить бота
|
||||
<ArrowUpRight size={18} />
|
||||
</Link>
|
||||
</PageHero>
|
||||
|
||||
<section className="px-6 py-20">
|
||||
<div className="mx-auto grid max-w-6xl gap-5 lg:grid-cols-2">
|
||||
{platforms.map((platform) => (
|
||||
<div
|
||||
key={platform.title}
|
||||
className="rounded-2xl border border-white/[0.06] bg-base-900/50 p-8"
|
||||
>
|
||||
<div className="mb-5 flex h-11 w-11 items-center justify-center rounded-xl border border-blue-500/25 bg-blue-500/10 text-blue-400">
|
||||
<platform.icon size={20} strokeWidth={1.75} />
|
||||
</div>
|
||||
<h3 className="font-display text-xl font-medium">{platform.title}</h3>
|
||||
<p className="mt-3 text-ink-500">{platform.description}</p>
|
||||
<ul className="mt-6 space-y-3">
|
||||
{platform.points.map((point) => (
|
||||
<li key={point} className="flex items-start gap-2.5 text-sm text-ink-300">
|
||||
<Check size={17} className="mt-0.5 shrink-0 text-blue-400" />
|
||||
{point}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="px-6 py-20">
|
||||
<div className="mx-auto max-w-6xl">
|
||||
<SectionEyebrow>Сценарии использования</SectionEyebrow>
|
||||
<h2 className="font-display text-3xl font-medium sm:text-4xl">
|
||||
Что умеют наши боты
|
||||
</h2>
|
||||
|
||||
<div className="mt-12 grid gap-5 sm:grid-cols-2 lg:grid-cols-3">
|
||||
{useCases.map((item) => (
|
||||
<div
|
||||
key={item.title}
|
||||
className="rounded-2xl border border-white/[0.06] bg-base-900/40 p-6"
|
||||
>
|
||||
<div className="mb-4 flex h-10 w-10 items-center justify-center rounded-lg border border-white/[0.08] bg-white/[0.03] text-blue-400">
|
||||
<item.icon size={18} strokeWidth={1.75} />
|
||||
</div>
|
||||
<h3 className="font-medium text-ink-100">{item.title}</h3>
|
||||
<p className="mt-2 text-sm leading-relaxed text-ink-500">
|
||||
{item.description}
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<CTASection
|
||||
title="Готовы автоматизировать общение с клиентами?"
|
||||
subtitle="Опишите задачу — предложим сценарий бота и сроки разработки."
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
import type { Metadata } from "next";
|
||||
import { Send, MessageCircle, Phone, Mail, MapPin, Clock } from "lucide-react";
|
||||
import SectionEyebrow from "@/components/SectionEyebrow";
|
||||
import NetworkGraphic from "@/components/NetworkGraphic";
|
||||
import ContactForm from "@/components/ContactForm";
|
||||
import { contacts } from "@/config/contacts";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Контакты",
|
||||
description: "Свяжитесь с командой LabNetHub через форму, Telegram, WhatsApp или email.",
|
||||
};
|
||||
|
||||
const directContacts = [
|
||||
{
|
||||
icon: Send,
|
||||
label: "Telegram",
|
||||
value: "Написать в чат",
|
||||
href: contacts.telegramBot,
|
||||
},
|
||||
{
|
||||
icon: Phone,
|
||||
label: "WhatsApp",
|
||||
value: "Написать в WhatsApp",
|
||||
href: contacts.whatsapp,
|
||||
},
|
||||
{
|
||||
icon: Mail,
|
||||
label: "Email",
|
||||
value: contacts.email,
|
||||
href: `mailto:${contacts.email}`,
|
||||
},
|
||||
{
|
||||
icon: MessageCircle,
|
||||
label: "ВКонтакте",
|
||||
value: "Наше сообщество",
|
||||
href: contacts.vk,
|
||||
},
|
||||
];
|
||||
|
||||
export default function ContactsPage() {
|
||||
return (
|
||||
<>
|
||||
<section className="relative overflow-hidden border-b border-white/[0.06] px-6 pb-16 pt-32 sm:pb-20 sm:pt-40">
|
||||
<div className="pointer-events-none absolute right-0 top-0 w-[420px] max-w-[60%] opacity-70 sm:opacity-100">
|
||||
<NetworkGraphic className="w-full" />
|
||||
</div>
|
||||
<div className="mx-auto max-w-3xl">
|
||||
<SectionEyebrow>Контакты</SectionEyebrow>
|
||||
<h1 className="text-balance font-display text-4xl font-medium leading-[1.1] sm:text-5xl">
|
||||
Свяжитесь <span className="text-gradient-blue">с нами</span>
|
||||
</h1>
|
||||
<p className="mt-5 max-w-xl text-lg leading-relaxed text-ink-500">
|
||||
Расскажите о задаче — предложим решение и сроки. Форма ниже
|
||||
приходит нам напрямую в Telegram.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="px-6 py-20">
|
||||
<div className="mx-auto grid max-w-6xl gap-12 lg:grid-cols-[1.1fr_0.9fr]">
|
||||
<div>
|
||||
<h2 className="mb-6 font-display text-xl font-medium">
|
||||
Напишите нам
|
||||
</h2>
|
||||
<ContactForm />
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2 className="mb-6 font-display text-xl font-medium">
|
||||
Прямые контакты
|
||||
</h2>
|
||||
<div className="space-y-3">
|
||||
{directContacts.map((c) => (
|
||||
<a
|
||||
key={c.label}
|
||||
href={c.href}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="flex items-center gap-4 rounded-xl border border-white/[0.06] bg-base-900/50 p-4 transition-colors hover:border-blue-500/30"
|
||||
>
|
||||
<div className="flex h-10 w-10 shrink-0 items-center justify-center rounded-lg border border-blue-500/25 bg-blue-500/10 text-blue-400">
|
||||
<c.icon size={18} strokeWidth={1.75} />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm text-ink-500">{c.label}</p>
|
||||
<p className="font-medium text-ink-100">{c.value}</p>
|
||||
</div>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="mt-6 space-y-3 border-t border-white/[0.06] pt-6">
|
||||
<div className="flex items-center gap-3 text-sm text-ink-500">
|
||||
<MapPin size={16} className="text-ink-700" />
|
||||
{contacts.city}
|
||||
</div>
|
||||
<div className="flex items-center gap-3 text-sm text-ink-500">
|
||||
<Clock size={16} className="text-ink-700" />
|
||||
{contacts.workingHours}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
import type { Metadata } from "next";
|
||||
import Link from "next/link";
|
||||
import { ArrowUpRight, Check, Lock, Wallet, Settings2, Database } from "lucide-react";
|
||||
import PageHero from "@/components/PageHero";
|
||||
import SectionEyebrow from "@/components/SectionEyebrow";
|
||||
import CTASection from "@/components/CTASection";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Настройка и интеграция CRM",
|
||||
description:
|
||||
"Установка, настройка и интеграция CRM-систем с открытым исходным кодом под процессы вашего бизнеса.",
|
||||
};
|
||||
|
||||
const benefits = [
|
||||
{
|
||||
icon: Wallet,
|
||||
title: "Без лицензионных платежей",
|
||||
description: "Открытый исходный код — платите за настройку, а не за подписку на каждого пользователя.",
|
||||
},
|
||||
{
|
||||
icon: Lock,
|
||||
title: "Данные остаются у вас",
|
||||
description: "CRM разворачивается на вашем сервере — полный контроль над данными клиентов.",
|
||||
},
|
||||
{
|
||||
icon: Settings2,
|
||||
title: "Гибкая настройка",
|
||||
description: "Дорабатываем систему под ваши процессы, а не подстраиваем бизнес под шаблон.",
|
||||
},
|
||||
{
|
||||
icon: Database,
|
||||
title: "Свобода интеграций",
|
||||
description: "Подключаем сайт, боты, почту и другие сервисы без ограничений вендора.",
|
||||
},
|
||||
];
|
||||
|
||||
const systems = [
|
||||
{
|
||||
name: "EspoCRM",
|
||||
description: "Гибкая CRM с удобным конструктором сущностей и процессов под любые отрасли.",
|
||||
},
|
||||
{
|
||||
name: "SuiteCRM",
|
||||
description: "Развитая система с модулями продаж, поддержки и маркетинга из коробки.",
|
||||
},
|
||||
{
|
||||
name: "Odoo CRM",
|
||||
description: "Часть экосистемы Odoo — легко расширяется складом, документами и бухгалтерией.",
|
||||
},
|
||||
];
|
||||
|
||||
const included = [
|
||||
"Установка и настройка CRM на сервере",
|
||||
"Настройка воронок продаж и полей под ваши процессы",
|
||||
"Интеграция с сайтом, ботами и почтой",
|
||||
"Перенос текущей базы клиентов",
|
||||
"Обучение сотрудников работе с системой",
|
||||
"Техническая поддержка после запуска",
|
||||
];
|
||||
|
||||
export default function CrmPage() {
|
||||
return (
|
||||
<>
|
||||
<PageHero
|
||||
eyebrow="CRM-системы"
|
||||
title="Настройка и"
|
||||
highlight="интеграция CRM"
|
||||
subtitle="Устанавливаем, настраиваем и интегрируем CRM с открытым исходным кодом — под процессы именно вашего бизнеса."
|
||||
>
|
||||
<Link
|
||||
href="/contacts"
|
||||
className="inline-flex items-center gap-1.5 rounded-full bg-blue-500 px-6 py-3.5 font-medium text-white transition-transform hover:scale-[1.03]"
|
||||
>
|
||||
Обсудить внедрение
|
||||
<ArrowUpRight size={18} />
|
||||
</Link>
|
||||
</PageHero>
|
||||
|
||||
<section className="px-6 py-20">
|
||||
<div className="mx-auto max-w-6xl">
|
||||
<SectionEyebrow>Почему open source</SectionEyebrow>
|
||||
<div className="mt-8 grid gap-8 sm:grid-cols-2 lg:grid-cols-4">
|
||||
{benefits.map((b) => (
|
||||
<div key={b.title}>
|
||||
<div className="mb-4 flex h-10 w-10 items-center justify-center rounded-lg border border-white/[0.08] bg-white/[0.03] text-blue-400">
|
||||
<b.icon size={18} strokeWidth={1.75} />
|
||||
</div>
|
||||
<h3 className="font-medium text-ink-100">{b.title}</h3>
|
||||
<p className="mt-2 text-sm leading-relaxed text-ink-500">
|
||||
{b.description}
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="px-6 py-20">
|
||||
<div className="mx-auto max-w-6xl">
|
||||
<SectionEyebrow>С какими системами работаем</SectionEyebrow>
|
||||
<h2 className="font-display text-3xl font-medium sm:text-4xl">
|
||||
Примеры CRM с открытым кодом
|
||||
</h2>
|
||||
<div className="mt-12 grid gap-5 lg:grid-cols-3">
|
||||
{systems.map((s) => (
|
||||
<div
|
||||
key={s.name}
|
||||
className="rounded-2xl border border-white/[0.06] bg-base-900/50 p-7"
|
||||
>
|
||||
<h3 className="font-display text-lg font-medium">{s.name}</h3>
|
||||
<p className="mt-3 text-sm leading-relaxed text-ink-500">
|
||||
{s.description}
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<p className="mt-6 text-sm text-ink-700">
|
||||
Также работаем с другими open-source CRM — подберём систему под ваши задачи и бюджет.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="px-6 py-20">
|
||||
<div className="mx-auto max-w-6xl rounded-3xl border border-white/[0.06] bg-base-900/40 p-10">
|
||||
<SectionEyebrow>Что входит в услугу</SectionEyebrow>
|
||||
<div className="mt-6 grid gap-4 sm:grid-cols-2">
|
||||
{included.map((item) => (
|
||||
<div key={item} className="flex items-start gap-2.5">
|
||||
<Check size={17} className="mt-0.5 shrink-0 text-blue-400" />
|
||||
<span className="text-ink-300">{item}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<CTASection
|
||||
title="Хотите навести порядок в клиентской базе?"
|
||||
subtitle="Расскажем, какая CRM подойдёт именно вашим процессам."
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer base {
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
body {
|
||||
@apply bg-base-950 text-ink-100 font-body antialiased;
|
||||
background-image: theme("backgroundImage.grid-fade");
|
||||
background-attachment: fixed;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4 {
|
||||
@apply font-display text-ink-100;
|
||||
}
|
||||
|
||||
::selection {
|
||||
@apply bg-blue-600/40 text-ink-100;
|
||||
}
|
||||
|
||||
:focus-visible {
|
||||
outline: 2px solid theme("colors.blue.400");
|
||||
outline-offset: 3px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 10px;
|
||||
}
|
||||
::-webkit-scrollbar-track {
|
||||
@apply bg-base-950;
|
||||
}
|
||||
::-webkit-scrollbar-thumb {
|
||||
@apply bg-base-700 rounded-full;
|
||||
}
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
@apply bg-blue-700;
|
||||
}
|
||||
}
|
||||
|
||||
@layer utilities {
|
||||
.text-gradient-blue {
|
||||
@apply bg-clip-text text-transparent bg-gradient-to-r from-blue-400 to-blue-600;
|
||||
}
|
||||
.text-gradient-green {
|
||||
@apply bg-clip-text text-transparent bg-gradient-to-r from-green-300 to-green-500;
|
||||
}
|
||||
.clip-corner {
|
||||
clip-path: polygon(0 0, 100% 0, 100% calc(100% - 22px), calc(100% - 22px) 100%, 0 100%);
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
animation-duration: 0.001ms !important;
|
||||
animation-iteration-count: 1 !important;
|
||||
transition-duration: 0.001ms !important;
|
||||
scroll-behavior: auto !important;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
import type { Metadata } from "next";
|
||||
import Link from "next/link";
|
||||
import {
|
||||
ArrowUpRight,
|
||||
Check,
|
||||
MapPin,
|
||||
Globe,
|
||||
Gauge,
|
||||
Settings2,
|
||||
Cpu,
|
||||
} from "lucide-react";
|
||||
import PageHero from "@/components/PageHero";
|
||||
import SectionEyebrow from "@/components/SectionEyebrow";
|
||||
import CTASection from "@/components/CTASection";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Хостинг и серверы",
|
||||
description:
|
||||
"VDS/VPS на собственных серверах в Астрахани и у партнёров по всему миру. NVMe, SLA 99.9%, защита от DDoS.",
|
||||
};
|
||||
|
||||
const features = [
|
||||
{
|
||||
icon: MapPin,
|
||||
title: "Собственный дата-центр",
|
||||
description: "Современное оборудование в нашем дата-центре в Астрахани.",
|
||||
},
|
||||
{
|
||||
icon: Globe,
|
||||
title: "Локации по всему миру",
|
||||
description: "Европа, Азия, США и другие регионы у партнёров.",
|
||||
},
|
||||
{
|
||||
icon: Gauge,
|
||||
title: "Высокая производительность",
|
||||
description: "NVMe-диски и мощные процессоры для стабильной нагрузки.",
|
||||
},
|
||||
{
|
||||
icon: Settings2,
|
||||
title: "Гибкие конфигурации",
|
||||
description: "Соберём сервер под ваши задачи, а не по шаблону.",
|
||||
},
|
||||
];
|
||||
|
||||
const specs = [
|
||||
"От 1 до 32 vCPU",
|
||||
"От 1 до 128 GB RAM",
|
||||
"NVMe SSD",
|
||||
"Linux / Windows",
|
||||
"SLA 99.9%",
|
||||
"Защита от DDoS",
|
||||
"Резервное копирование",
|
||||
"Панель управления и API",
|
||||
];
|
||||
|
||||
export default function HostingPage() {
|
||||
return (
|
||||
<>
|
||||
<PageHero
|
||||
accent="green"
|
||||
eyebrow="Хостинг и серверы"
|
||||
title="Надёжные серверы"
|
||||
highlight="по всему миру"
|
||||
subtitle="Предоставляем мощные и стабильные VDS/VPS — на собственных серверах в Астрахани и в других локациях у проверенных партнёров."
|
||||
>
|
||||
<Link
|
||||
href="/contacts"
|
||||
className="inline-flex items-center gap-1.5 rounded-full bg-green-500 px-6 py-3.5 font-medium text-base-950 transition-transform hover:scale-[1.03]"
|
||||
>
|
||||
Подобрать сервер
|
||||
<ArrowUpRight size={18} />
|
||||
</Link>
|
||||
</PageHero>
|
||||
|
||||
<section className="px-6 py-20">
|
||||
<div className="mx-auto max-w-6xl grid gap-8 sm:grid-cols-2 lg:grid-cols-4">
|
||||
{features.map((f) => (
|
||||
<div key={f.title}>
|
||||
<div className="mb-4 flex h-10 w-10 items-center justify-center rounded-lg border border-green-500/25 bg-green-500/10 text-green-400">
|
||||
<f.icon size={18} strokeWidth={1.75} />
|
||||
</div>
|
||||
<h3 className="font-medium text-ink-100">{f.title}</h3>
|
||||
<p className="mt-2 text-sm leading-relaxed text-ink-500">
|
||||
{f.description}
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="px-6 py-20">
|
||||
<div className="mx-auto max-w-4xl rounded-3xl border border-green-500/20 bg-green-500/[0.04] p-10">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="flex h-11 w-11 items-center justify-center rounded-xl border border-green-500/25 bg-green-500/10 text-green-400">
|
||||
<Cpu size={20} strokeWidth={1.75} />
|
||||
</div>
|
||||
<h2 className="font-display text-xl font-medium">
|
||||
VDS/VPS от LabNetHub
|
||||
</h2>
|
||||
</div>
|
||||
<div className="mt-8 grid gap-4 sm:grid-cols-2">
|
||||
{specs.map((spec) => (
|
||||
<div key={spec} className="flex items-start gap-2.5">
|
||||
<Check size={17} className="mt-0.5 shrink-0 text-green-400" />
|
||||
<span className="text-ink-300">{spec}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<p className="mt-8 text-sm text-ink-500">
|
||||
Стоимость зависит от конфигурации и локации — рассчитаем тариф под
|
||||
вашу задачу.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="px-6 pb-4">
|
||||
<div className="mx-auto max-w-6xl">
|
||||
<SectionEyebrow accent="green">Размещение проектов</SectionEyebrow>
|
||||
<p className="max-w-2xl text-ink-500">
|
||||
Размещаем сайты и боты, разработанные нашей командой, на
|
||||
собственных серверах или у партнёров — без необходимости искать
|
||||
хостинг отдельно и разбираться в настройке сервера самостоятельно.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<CTASection
|
||||
title="Нужен сервер под проект?"
|
||||
subtitle="Подберём конфигурацию и локацию, поможем с переносом и настройкой."
|
||||
accent="green"
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40">
|
||||
<defs>
|
||||
<linearGradient id="g" x1="0" y1="0" x2="1" y2="1">
|
||||
<stop offset="0%" stop-color="#6FA8FF" />
|
||||
<stop offset="100%" stop-color="#2F63EB" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect width="40" height="40" rx="9" fill="#0A1428" />
|
||||
<polygon points="10,7 18,7 15,32 7,32" fill="#F5F7FB" />
|
||||
<polygon points="14,32 33,32 28,24 18,24" fill="url(#g)" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 440 B |
@@ -0,0 +1,59 @@
|
||||
import type { Metadata } from "next";
|
||||
import { Unbounded, Manrope, JetBrains_Mono } from "next/font/google";
|
||||
import "./globals.css";
|
||||
import Header from "@/components/Header";
|
||||
import Footer from "@/components/Footer";
|
||||
|
||||
const unbounded = Unbounded({
|
||||
subsets: ["latin", "cyrillic"],
|
||||
weight: ["400", "500", "600"],
|
||||
variable: "--font-unbounded",
|
||||
display: "swap",
|
||||
});
|
||||
|
||||
const manrope = Manrope({
|
||||
subsets: ["latin", "cyrillic"],
|
||||
weight: ["400", "500", "600", "700"],
|
||||
variable: "--font-manrope",
|
||||
display: "swap",
|
||||
});
|
||||
|
||||
const jetbrainsMono = JetBrains_Mono({
|
||||
subsets: ["latin", "cyrillic"],
|
||||
weight: ["400", "500"],
|
||||
variable: "--font-jetbrains",
|
||||
display: "swap",
|
||||
});
|
||||
|
||||
export const metadata: Metadata = {
|
||||
metadataBase: new URL("https://labnethub.ru"),
|
||||
title: {
|
||||
default: "LabNetHub — комплексные IT-решения для бизнеса",
|
||||
template: "%s — LabNetHub",
|
||||
},
|
||||
description:
|
||||
"Сайты, боты для соцсетей, настройка CRM, хостинг и IT-поддержка. От идеи до стабильной работы вашей инфраструктуры.",
|
||||
openGraph: {
|
||||
title: "LabNetHub — комплексные IT-решения для бизнеса",
|
||||
description:
|
||||
"Сайты, боты для соцсетей, настройка CRM, хостинг и IT-поддержка.",
|
||||
locale: "ru_RU",
|
||||
type: "website",
|
||||
},
|
||||
};
|
||||
|
||||
export default function RootLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<html lang="ru" className={`${unbounded.variable} ${manrope.variable} ${jetbrainsMono.variable}`}>
|
||||
<body>
|
||||
<Header />
|
||||
<main className="min-h-screen pt-[73px]">{children}</main>
|
||||
<Footer />
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
import Link from "next/link";
|
||||
import { ArrowUpRight, ShieldCheck, Rocket, SlidersHorizontal, Headphones } from "lucide-react";
|
||||
import SectionEyebrow from "@/components/SectionEyebrow";
|
||||
import ServiceCard from "@/components/ServiceCard";
|
||||
import FeatureBadge from "@/components/FeatureBadge";
|
||||
import NetworkGraphic from "@/components/NetworkGraphic";
|
||||
import CTASection from "@/components/CTASection";
|
||||
import { services } from "@/config/services";
|
||||
|
||||
export default function HomePage() {
|
||||
return (
|
||||
<>
|
||||
<section className="relative overflow-hidden px-6 pb-20 pt-32 sm:pb-28 sm:pt-40">
|
||||
<div className="pointer-events-none absolute right-[-40px] top-10 w-[480px] max-w-[65%] opacity-60 sm:opacity-100">
|
||||
<NetworkGraphic accent="blue" className="w-full" />
|
||||
</div>
|
||||
|
||||
<div className="mx-auto max-w-3xl">
|
||||
<SectionEyebrow>Технологии · Решения · Поддержка</SectionEyebrow>
|
||||
<h1 className="text-balance font-display text-4xl font-medium leading-[1.08] sm:text-6xl">
|
||||
Комплексные IT-решения{" "}
|
||||
<span className="text-gradient-blue">для вашего бизнеса</span>
|
||||
</h1>
|
||||
<p className="mt-6 max-w-xl text-lg leading-relaxed text-ink-500">
|
||||
От идеи до стабильной работы инфраструктуры: сайты, боты для
|
||||
соцсетей, CRM, серверы и техническая поддержка — в одной команде.
|
||||
</p>
|
||||
|
||||
<div className="mt-9 flex flex-wrap gap-3">
|
||||
<Link
|
||||
href="/contacts"
|
||||
className="inline-flex items-center gap-1.5 rounded-full bg-blue-500 px-6 py-3.5 font-medium text-white transition-transform hover:scale-[1.03]"
|
||||
>
|
||||
Обсудить проект
|
||||
<ArrowUpRight size={18} />
|
||||
</Link>
|
||||
<Link
|
||||
href="#services"
|
||||
className="inline-flex items-center gap-1.5 rounded-full border border-white/[0.12] px-6 py-3.5 font-medium text-ink-100 transition-colors hover:bg-white/[0.05]"
|
||||
>
|
||||
Смотреть услуги
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mx-auto mt-16 grid max-w-3xl grid-cols-2 gap-6 border-t border-white/[0.06] pt-8 sm:grid-cols-4">
|
||||
{[
|
||||
["5", "направлений услуг"],
|
||||
["24/7", "техподдержка"],
|
||||
["99.9%", "SLA на серверах"],
|
||||
["1", "команда на весь проект"],
|
||||
].map(([value, label]) => (
|
||||
<div key={label}>
|
||||
<p className="font-display text-2xl text-ink-100">{value}</p>
|
||||
<p className="mt-1 text-sm text-ink-500">{label}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="services" className="scroll-mt-24 px-6 py-20">
|
||||
<div className="mx-auto max-w-6xl">
|
||||
<div className="max-w-2xl">
|
||||
<SectionEyebrow>Что мы делаем</SectionEyebrow>
|
||||
<h2 className="font-display text-3xl font-medium sm:text-4xl">
|
||||
Всё для роста вашего бизнеса — в одном месте
|
||||
</h2>
|
||||
<p className="mt-4 text-ink-500">
|
||||
Каждое направление можно заказать отдельно или как часть общего
|
||||
решения — от первого сайта до полноценной IT-инфраструктуры.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="mt-12 grid gap-5 sm:grid-cols-2 lg:grid-cols-3">
|
||||
{services.map((service) => (
|
||||
<ServiceCard key={service.key} service={service} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="px-6 py-20">
|
||||
<div className="mx-auto max-w-6xl rounded-3xl border border-white/[0.06] bg-base-900/40 p-10">
|
||||
<SectionEyebrow>Почему выбирают нас</SectionEyebrow>
|
||||
<div className="mt-6 grid gap-8 sm:grid-cols-2 lg:grid-cols-4">
|
||||
<FeatureBadge
|
||||
icon={ShieldCheck}
|
||||
title="Надёжность"
|
||||
description="Гарантия качества и стабильной работы решений"
|
||||
/>
|
||||
<FeatureBadge
|
||||
icon={Rocket}
|
||||
title="Скорость"
|
||||
description="Быстрое выполнение задач и запуск проектов"
|
||||
/>
|
||||
<FeatureBadge
|
||||
icon={SlidersHorizontal}
|
||||
title="Индивидуальный подход"
|
||||
description="Решения под конкретные задачи вашего бизнеса"
|
||||
/>
|
||||
<FeatureBadge
|
||||
icon={Headphones}
|
||||
title="Поддержка 24/7"
|
||||
description="Мы всегда на связи и готовы помочь"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<CTASection />
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
import type { Metadata } from "next";
|
||||
import Link from "next/link";
|
||||
import { ArrowUpRight, Server, Activity, Wrench, MessageSquare, Check } from "lucide-react";
|
||||
import PageHero from "@/components/PageHero";
|
||||
import SectionEyebrow from "@/components/SectionEyebrow";
|
||||
import CTASection from "@/components/CTASection";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "IT-поддержка и инфраструктура",
|
||||
description:
|
||||
"Обслуживание IT-инфраструктуры бизнеса: сборка серверов, мониторинг, устранение сбоев, консультации.",
|
||||
};
|
||||
|
||||
const coverage = [
|
||||
{
|
||||
icon: Server,
|
||||
title: "Обслуживание серверов",
|
||||
description: "Настройка, обновление и сопровождение серверного оборудования.",
|
||||
},
|
||||
{
|
||||
icon: Activity,
|
||||
title: "Мониторинг и профилактика",
|
||||
description: "Отслеживаем состояние систем, чтобы предупредить сбои заранее.",
|
||||
},
|
||||
{
|
||||
icon: Wrench,
|
||||
title: "Сборка и настройка оборудования",
|
||||
description: "Подбираем и настраиваем технику под задачи вашей команды.",
|
||||
},
|
||||
{
|
||||
icon: MessageSquare,
|
||||
title: "Консультации",
|
||||
description: "Помогаем принимать решения по развитию IT-инфраструктуры.",
|
||||
},
|
||||
];
|
||||
|
||||
const formats = [
|
||||
{
|
||||
title: "Разовая задача",
|
||||
description:
|
||||
"Точечная помощь: настройка сервера, устранение конкретной проблемы, консультация.",
|
||||
points: ["Без долгосрочных обязательств", "Оценка сроков после диагностики задачи"],
|
||||
},
|
||||
{
|
||||
title: "Постоянное обслуживание",
|
||||
description:
|
||||
"Регулярное сопровождение инфраструктуры: мониторинг, обновления, приоритетная поддержка.",
|
||||
points: ["Согласованный формат и время реакции", "Профилактика вместо экстренных починок"],
|
||||
},
|
||||
];
|
||||
|
||||
export default function SupportPage() {
|
||||
return (
|
||||
<>
|
||||
<PageHero
|
||||
eyebrow="IT-поддержка"
|
||||
title="Поддержка вашей"
|
||||
highlight="IT-инфраструктуры"
|
||||
subtitle="Обслуживаем существующую инфраструктуру бизнеса: от сборки и настройки оборудования до мониторинга и устранения сбоев."
|
||||
>
|
||||
<Link
|
||||
href="/contacts"
|
||||
className="inline-flex items-center gap-1.5 rounded-full bg-blue-500 px-6 py-3.5 font-medium text-white transition-transform hover:scale-[1.03]"
|
||||
>
|
||||
Обсудить задачу
|
||||
<ArrowUpRight size={18} />
|
||||
</Link>
|
||||
</PageHero>
|
||||
|
||||
<section className="px-6 py-20">
|
||||
<div className="mx-auto max-w-6xl grid gap-8 sm:grid-cols-2 lg:grid-cols-4">
|
||||
{coverage.map((c) => (
|
||||
<div key={c.title}>
|
||||
<div className="mb-4 flex h-10 w-10 items-center justify-center rounded-lg border border-white/[0.08] bg-white/[0.03] text-blue-400">
|
||||
<c.icon size={18} strokeWidth={1.75} />
|
||||
</div>
|
||||
<h3 className="font-medium text-ink-100">{c.title}</h3>
|
||||
<p className="mt-2 text-sm leading-relaxed text-ink-500">
|
||||
{c.description}
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="px-6 py-20">
|
||||
<div className="mx-auto max-w-6xl">
|
||||
<SectionEyebrow>Формат работы</SectionEyebrow>
|
||||
<h2 className="font-display text-3xl font-medium sm:text-4xl">
|
||||
Как удобно вам
|
||||
</h2>
|
||||
<div className="mt-12 grid gap-5 lg:grid-cols-2">
|
||||
{formats.map((f) => (
|
||||
<div
|
||||
key={f.title}
|
||||
className="rounded-2xl border border-white/[0.06] bg-base-900/50 p-8"
|
||||
>
|
||||
<h3 className="font-display text-lg font-medium">{f.title}</h3>
|
||||
<p className="mt-3 text-ink-500">{f.description}</p>
|
||||
<ul className="mt-6 space-y-3">
|
||||
{f.points.map((point) => (
|
||||
<li key={point} className="flex items-start gap-2.5 text-sm text-ink-300">
|
||||
<Check size={17} className="mt-0.5 shrink-0 text-blue-400" />
|
||||
{point}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<CTASection
|
||||
title="Нужна помощь с инфраструктурой?"
|
||||
subtitle="Опишите ситуацию — предложим формат работы и следующий шаг."
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
import type { Metadata } from "next";
|
||||
import Link from "next/link";
|
||||
import { Check, ArrowUpRight } from "lucide-react";
|
||||
import PageHero from "@/components/PageHero";
|
||||
import SectionEyebrow from "@/components/SectionEyebrow";
|
||||
import CTASection from "@/components/CTASection";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Сайты для бизнеса",
|
||||
description:
|
||||
"Разработка сайтов-визиток и полноценных корпоративных сайтов для малого и среднего бизнеса.",
|
||||
};
|
||||
|
||||
const offers = [
|
||||
{
|
||||
title: "Сайт-визитка",
|
||||
description:
|
||||
"Компактный сайт на 1–5 страниц: рассказать о компании, показать услуги и получить первые заявки.",
|
||||
points: [
|
||||
"Адаптивная вёрстка под любые экраны",
|
||||
"Форма заявки и контакты на видном месте",
|
||||
"Быстрый запуск — от нескольких дней",
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Корпоративный сайт под ключ",
|
||||
description:
|
||||
"Полноценный сайт для компании: каталог, блог, личный кабинет, интеграции с CRM и сервисами.",
|
||||
points: [
|
||||
"Структура под задачи бизнеса, а не шаблон",
|
||||
"SEO-оптимизация и подготовка к продвижению",
|
||||
"Интеграция с CRM, ботами и аналитикой",
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
const steps = [
|
||||
{
|
||||
n: "01",
|
||||
title: "Бриф",
|
||||
description: "Обсуждаем задачи бизнеса, аудиторию и нужный результат.",
|
||||
},
|
||||
{
|
||||
n: "02",
|
||||
title: "Прототип и дизайн",
|
||||
description: "Собираем структуру страниц и визуальный стиль сайта.",
|
||||
},
|
||||
{
|
||||
n: "03",
|
||||
title: "Разработка",
|
||||
description: "Вёрстка и программирование с адаптацией под все устройства.",
|
||||
},
|
||||
{
|
||||
n: "04",
|
||||
title: "Тестирование",
|
||||
description: "Проверяем работу форм, скорость и корректность на разных устройствах.",
|
||||
},
|
||||
{
|
||||
n: "05",
|
||||
title: "Запуск и поддержка",
|
||||
description: "Публикуем сайт и остаёмся на связи для доработок.",
|
||||
},
|
||||
];
|
||||
|
||||
const included = [
|
||||
"Адаптивная вёрстка под мобильные, планшеты и десктоп",
|
||||
"SEO-оптимизация: метатеги, семантическая разметка, скорость загрузки",
|
||||
"Интеграция форм обратной связи с Telegram, email или CRM",
|
||||
"Подключение аналитики (Яндекс.Метрика, Google Analytics)",
|
||||
"Настройка домена, SSL-сертификата и хостинга",
|
||||
"Инструкция по управлению сайтом после запуска",
|
||||
];
|
||||
|
||||
export default function WebsitesPage() {
|
||||
return (
|
||||
<>
|
||||
<PageHero
|
||||
eyebrow="Разработка сайтов"
|
||||
title="Сайты, которые"
|
||||
highlight="работают на бизнес"
|
||||
subtitle="Разрабатываем современные и адаптивные сайты для вашего бизнеса — от простой визитки до полноценного корпоративного портала."
|
||||
>
|
||||
<Link
|
||||
href="/contacts"
|
||||
className="inline-flex items-center gap-1.5 rounded-full bg-blue-500 px-6 py-3.5 font-medium text-white transition-transform hover:scale-[1.03]"
|
||||
>
|
||||
Обсудить проект
|
||||
<ArrowUpRight size={18} />
|
||||
</Link>
|
||||
<Link
|
||||
href="#process"
|
||||
className="inline-flex items-center gap-1.5 rounded-full border border-white/[0.12] px-6 py-3.5 font-medium text-ink-100 transition-colors hover:bg-white/[0.05]"
|
||||
>
|
||||
Как мы работаем
|
||||
</Link>
|
||||
</PageHero>
|
||||
|
||||
<section className="px-6 py-20">
|
||||
<div className="mx-auto grid max-w-6xl gap-5 lg:grid-cols-2">
|
||||
{offers.map((offer) => (
|
||||
<div
|
||||
key={offer.title}
|
||||
className="rounded-2xl border border-white/[0.06] bg-base-900/50 p-8"
|
||||
>
|
||||
<h3 className="font-display text-xl font-medium">{offer.title}</h3>
|
||||
<p className="mt-3 text-ink-500">{offer.description}</p>
|
||||
<ul className="mt-6 space-y-3">
|
||||
{offer.points.map((point) => (
|
||||
<li key={point} className="flex items-start gap-2.5 text-sm text-ink-300">
|
||||
<Check size={17} className="mt-0.5 shrink-0 text-blue-400" />
|
||||
{point}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="process" className="scroll-mt-24 px-6 py-20">
|
||||
<div className="mx-auto max-w-6xl">
|
||||
<SectionEyebrow>Как мы работаем</SectionEyebrow>
|
||||
<h2 className="font-display text-3xl font-medium sm:text-4xl">
|
||||
Пять шагов от идеи до запуска
|
||||
</h2>
|
||||
|
||||
<div className="mt-12 grid gap-8 sm:grid-cols-2 lg:grid-cols-5">
|
||||
{steps.map((step) => (
|
||||
<div key={step.n}>
|
||||
<p className="font-mono text-sm text-blue-400">{step.n}</p>
|
||||
<h3 className="mt-2 font-display text-lg font-medium">
|
||||
{step.title}
|
||||
</h3>
|
||||
<p className="mt-2 text-sm leading-relaxed text-ink-500">
|
||||
{step.description}
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="px-6 py-20">
|
||||
<div className="mx-auto max-w-6xl rounded-3xl border border-white/[0.06] bg-base-900/40 p-10">
|
||||
<SectionEyebrow>Что входит в разработку</SectionEyebrow>
|
||||
<div className="mt-6 grid gap-4 sm:grid-cols-2">
|
||||
{included.map((item) => (
|
||||
<div key={item} className="flex items-start gap-2.5">
|
||||
<Check size={17} className="mt-0.5 shrink-0 text-blue-400" />
|
||||
<span className="text-ink-300">{item}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<CTASection />
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user