П/ВИН

Feberra Landing: миграция с Vercel и SEO-оптимизация

·8 мин чтения
Feberra Landing: миграция с Vercel и SEO-оптимизация

Когда проект начинается в v0 от Vercel, это удобно — быстрый старт, моментальный деплой, никаких забот об инфраструктуре. Но рано или поздно наступает момент, когда хочется контроля: своя CI/CD-цепочка, свои правила деплоя, своя SEO-стратегия без зависимости от платформы. Именно в такой ситуации оказался проект feberra.com — AI-платформа для создания видео из текста. Лендинг жил на GitHub, деплоился через Vercel, и пришло время переехать на нашу собственную инфраструктуру.

В этой статье расскажу, как мы провели полную миграцию Next.js-лендинга с Vercel на Dokploy, настроили автодеплой через GitHub webhook, и — что не менее важно — сделали полноценную SEO-оптимизацию с нуля: от sitemap до structured data и security headers.

Контекст: что было до миграции

Проект feberra-landing-page — типичный Next.js 15 лендинг, сгенерированный в v0. Внутри: красивый UI, блог с несколькими статьями, страницы категорий и тегов. Домен feberra.com уже был куплен и задеплоен — но через Vercel, с их CDN и их деплой-пайплайном.

Проблема не в том, что Vercel плохой. Проблема в том, что у нас уже есть своя инфраструктура на VPS с Dokploy — оркестратором, который умеет деплоить Docker-контейнеры, управлять доменами через Traefik и выдавать Let's Encrypt сертификаты. Все остальные проекты живут там. Feberra должен был жить там же.

Кроме того, SEO-аудит показал удручающую картину: нет sitemap.xml, нет robots.txt, нет structured data, нет security headers, meta-теги минимальные, OG-изображения отсутствуют. Для лендинга AI-продукта, который должен находиться в поиске — это катастрофа.

Шаг 1: Подготовка к Dockerized-деплою

Первое, что нужно сделать для любого Next.js-приложения при переезде на Docker — включить output: "standalone" в конфиге. Это говорит Next.js собрать приложение в минимальный bundle, который можно запустить без node_modules.

// next.config.mjs — было
const nextConfig = {
  // пусто или минимальная конфигурация от v0
};
 
// next.config.mjs — стало
const nextConfig = {
  output: "standalone",
  poweredByHeader: false, // скрываем X-Powered-By: Next.js
};

Далее — Dockerfile по проверенному multi-stage паттерну:

FROM node:20-alpine AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci
 
FROM node:20-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build
 
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
COPY --from=builder /app/public ./public
EXPOSE 3000
CMD ["node", "server.js"]

Tрёхэтапная сборка: deps устанавливает зависимости, builder собирает приложение, runner — финальный минимальный образ только с тем, что нужно для запуска. Размер финального образа получается существенно меньше, чем если бы мы тащили все node_modules в продакшен.

Отдельно убрали @vercel/analytics из layout.tsx и package.json — этот пакет предназначен специфически для платформы Vercel и на нашей инфраструктуре бесполезен.

Шаг 2: Настройка Dokploy и GitHub webhook

Докплой управляется через API. Создали приложение, настроили customGitUrl на репозиторий, указали Dockerfile как тип сборки, добавили домен feberra.com с автоматическим SSL через Let's Encrypt.

GitHub webhook настроен так, что каждый push в ветку main автоматически триггерит новый деплой. Это значит: пушишь изменения — через несколько минут они уже на продакшене. Никаких ручных шагов.

DNS A-запись направлена на VPS. Traefik, который стоит за Dokploy, автоматически получил SSL-сертификат от Let's Encrypt при первом обращении к домену. После деплоя проверка подтвердила: HTTPS работает, HTTP автоматически редиректит на HTTPS, страница отдаёт 200.

Шаг 3: SEO-аудит и план оптимизации

После успешной миграции взялись за SEO. Аудит показал полный список проблем, которые мы разбили на пять приоритетных чанков:

Critical Technical — канонические URL, security headers, noindex на технических страницах

On-Page SEO — title теги, H1 на страницах блога, structured data (BlogPosting, CollectionPage, Organization)

GEO (Generative Engine Optimization) — файл llms.txt для AI-поисковиков

Content Quality — динамические счётчики категорий, расширенные meta descriptions

Индексация — подключение Google Search Console и Яндекс Вебмастер

Шаг 4: Технические SEO-правки

Canonical URLs и noindex

Страницы тегов (/blog/tag/[tag]) и некоторые служебные страницы получили noindex, nofollow — они не несут уникального контента и не должны индексироваться:

// app/blog/tag/[tag]/page.tsx
export const metadata: Metadata = {
  robots: {
    index: false,
    follow: false,
  },
};

Для всех значимых страниц добавлены канонические URL через Next.js Metadata API:

export const metadata: Metadata = {
  alternates: {
    canonical: "https://feberra.com/blog",
  },
};

Security Headers

В next.config.mjs добавили стандартный набор security headers:

const securityHeaders = [
  { key: "X-Content-Type-Options", value: "nosniff" },
  { key: "X-Frame-Options", value: "DENY" },
  { key: "X-XSS-Protection", value: "1; mode=block" },
  { key: "Referrer-Policy", value: "strict-origin-when-cross-origin" },
  {
    key: "Permissions-Policy",
    value: "camera=(), microphone=(), geolocation=()",
  },
];

Это не только безопасность — Google учитывает наличие security headers при оценке качества сайта.

Sitemap и robots.txt

Next.js App Router поддерживает автогенерацию sitemap через файл sitemap.ts:

// app/sitemap.ts
import { MetadataRoute } from "next";
import { getAllPosts } from "@/lib/blog-data";
 
export default function sitemap(): MetadataRoute.Sitemap {
  const posts = getAllPosts();
  const postEntries = posts.map((post) => ({
    url: `https://feberra.com/blog/${post.slug}`,
    lastModified: new Date(post.date),
    changeFrequency: "monthly" as const,
    priority: 0.7,
  }));
 
  return [
    { url: "https://feberra.com", priority: 1.0, changeFrequency: "weekly" },
    { url: "https://feberra.com/blog", priority: 0.9, changeFrequency: "weekly" },
    ...postEntries,
  ];
}

Structured Data (JSON-LD)

Для главной страницы добавили Organization и FAQ schema:

const organizationSchema = {
  "@context": "https://schema.org",
  "@type": "Organization",
  "@id": "https://feberra.com/#organization",
  name: "Feberra",
  url: "https://feberra.com",
  sameAs: [
    "https://twitter.com/feberra",
    "https://linkedin.com/company/feberra",
  ],
};

Для статей блога — BlogPosting schema с автором, датой публикации и canonical URL. Для страницы блога — CollectionPage. Schema.org даёт поисковикам структурированное понимание контента, что прямо влияет на rich snippets в выдаче.

OG-изображения

Next.js умеет генерировать OG-изображения программно через opengraph-image.tsx:

import { ImageResponse } from "next/og";
 
export default function Image() {
  return new ImageResponse(
    (
      <div
        style={{
          background: "linear-gradient(135deg, #0f0f0f 0%, #1a1a2e 100%)",
          width: "100%",
          height: "100%",
          display: "flex",
          flexDirection: "column",
          alignItems: "center",
          justifyContent: "center",
        }}
      >
        <h1 style={{ color: "white", fontSize: 72 }}>Feberra</h1>
        <p style={{ color: "#888", fontSize: 32 }}>AI Video Generation</p>
      </div>
    ),
    { width: 1200, height: 630 }
  );
}

llms.txt — оптимизация для AI-поисковиков

Одна из интереснейших задач — добавить файл llms.txt. Это новый стандарт (аналог robots.txt, но для больших языковых моделей), который подсказывает AI-ассистентам и поисковикам на базе LLM, как понимать ваш сайт. Для AI-продукта вроде Feberra это особенно важно — целевая аудитория активно использует AI-инструменты для поиска.

# Feberra - AI Video Generation Platform

## About
Feberra is an AI platform that generates professional videos from text prompts.

## Key Pages
- Homepage: https://feberra.com
- Blog: https://feberra.com/blog

## Content
The blog covers AI video generation, use cases, tutorials and industry trends.

Результаты

После всех изменений и нескольких деплоев картина стала принципиально другой:

  • feberra.com работает на собственном VPS, за Traefik reverse proxy
  • HTTPS с автоматическим обновлением Let's Encrypt сертификата
  • Автодеплой — push в main → деплой через GitHub webhook без ручных действий
  • sitemap.xml генерируется динамически, включает все статьи блога
  • robots.txt корректно настроен, технические страницы закрыты от индексации
  • Structured data на всех ключевых страницах (Organization, BlogPosting, CollectionPage, FAQ)
  • Security headers полный набор
  • OG-изображения генерируются программно для каждой страницы
  • llms.txt для AI-поисковиков
  • 44 страницы успешно генерируются при билде (проверено в логах)

Bилд проходит чисто, все роуты корректны, время сборки — в пределах нормы для Next.js проекта такого размера.

Уроки и выводы

Первый урок: миграция с Vercel на собственный сервер — это не страшно, если у вас уже настроена инфраструктура. Ключевые шаги стандартны для любого Next.js проекта: output: standalone в конфиге, многоэтапный Dockerfile, настройка домена и webhook. Весь процесс занял меньше часа.

Второй урок: SEO нельзя откладывать. v0 генерирует красивый UI, но никакой SEO-базы — ни sitemap, ни structured data, ни корректных meta-тегов. Если вы используете v0 или аналогичные инструменты для быстрого старта, закладывайте время на SEO-аудит сразу после первого деплоя, а не через несколько месяцев.

Третий урок: Next.js App Router делает SEO удобным. Файловые конвенции sitemap.ts, robots.ts, opengraph-image.tsx, встроенный Metadata API — всё это позволяет держать SEO-логику рядом с кодом страниц, а не в отдельных конфигах. Документация Next.js по metadata — обязательное чтение для всех, кто делает продакшен-сайты.

Четвёртый урок: GEO (Generative Engine Optimization) — новая реальность. llms.txt — это ещё не устоявшийся стандарт, но направление понятно: AI-поисковики и ассистенты становятся значимым источником трафика, особенно для технологических продуктов. Для AI-платформы вроде Feberra игнорировать этот канал было бы странно. Стоит следить за развитием стандарта — инициатива llms.txt активно развивается.

Пятый урок, более общий: хорошая инфраструктура окупается. Наличие готового Dokploy-окружения с Traefik, Let's Encrypt и webhook-деплоем означает, что перенос нового проекта занимает минуты, а не дни. Инвестиции в инфраструктуру — это инвестиции в скорость всех последующих проектов.

Feberra теперь работает на нашей инфраструктуре, индексируется корректно, и готова к росту органического трафика. Следующий шаг — подключение Google Search Console для мониторинга позиций и выявления новых точек роста.

Паша Вин
Паша Вин

AI-инженер, предприниматель, маркетолог. Основатель feberra.com и x10seo.ru. 13 лет в перфоманс-маркетинге, 3 года в системной интеграции AI в бизнес.

Связанный проект

Feberra