← Все уроки
Урок 04

Прикручиваем бэкенд

Сервер, база данных и настоящая обработка заявок как у профи

Node.jsExpressSupabaseАдмин-панель
Скролль вниз ↓

Зачем нужен бэкенд?

В уроке 2 мы отправляли заявки напрямую в Telegram. Это работает, но...

Раньше (плохо)

🌐
Браузер
fetch напрямую
📱
Telegram
Токен бота виден в коде страницы
Любой может найти и использовать
Заявки нигде не сохраняются
Нет истории, нет статистики

Теперь (правильно)

🌐
Браузер
POST /api/lead
🖥️
Сервер
🗄️
Supabaseсохранить
📱
Telegramуведомить
🔒Токен скрыт на сервере
💾Данные сохранены в БД
📊Можно строить админку

Node.js + Express

🟢Node.js — JavaScript на сервере

Тот же язык что и в браузере, но теперь работает на компьютере/сервере. Можно работать с файлами, базами данных, API.

Express — фреймворк для API

Упрощает создание сервера. Один файл — и у тебя рабочий API.

🍽️Аналогия: Express = официант, который принимает заказы (запросы) и передаёт на кухню (обработку)
server.js — минимальный сервер
const express = require('express');
const app = express();

// Принимаем JSON
app.use(express.json());

// Обрабатываем заявку
app.post('/api/lead', (req, res) => {
  const { name, phone, message } = req.body;

  console.log('Новая заявка:', name, phone);

  res.json({ success: true });
});

// Запускаем сервер
app.listen(3000, () => {
  console.log('Сервер работает!');
});

Установка Node.js

1

Скачай Node.js

Открой nodejs.org и нажми LTS (рекомендуемая версия)

🌐
nodejs.org

Скачай LTS-версию (кнопка слева)

2

Установи

Запусти .msi файл, жми Next

→ Запусти node-v20.x.x.msi

→ Нажимай "Next" везде

→ Убедись что галочка "Add to PATH" стоит

3

Проверь установку

Открой терминал и проверь

#34d399]">$ node --version
v20.11.0

#34d399]">$ npm --version
10.2.0
Шаг 1

Создаём сервер

Создаём папку backend рядом с лендингом и просим Cursor написать сервер.

В терминале Cursor

mkdir backend cd backend npm init -y npm install express cors

В Cursor AI Chat

Создай файл server.js с Express-сервером: 1. Подключи express и cors 2. POST /api/lead — принимает {name, phone, message} 3. Логирует в консоль «Новая заявка: ...» 4. Возвращает {success: true} 5. Сервер слушает порт 3001

Cursor — my-landing
server.js×
const express = require('express');
const cors = require('cors');
const app = express();

app.use(cors());
app.use(express.json());

app.post('/api/lead',
  (req, res) => {
  const { name, phone,
    message } = req.body;
  console.log('Заявка:', name);
  res.json({ success: true });
});

app.listen(3001, () => {
  console.log('Сервер: 3001');
});
TERMINAL
$ node server.js Сервер: 3001

Что такое Supabase

Supabase — облачная база данных с красивым интерфейсом. Бесплатный тариф. Не нужно ничего устанавливать — всё в облаке.

PostgreSQL

Надёжная база данных. Используют Notion, Instagram, Spotify

Бесплатно

До 500 МБ и 50 000 запросов/мес — более чем достаточно

Готовый API

Supabase сам генерирует API для работы с данными

Supabase — my-landing-db
leads3 rows
idnamephonemessagestatus
1Иван Петров+7 999 123-45-67Хочу заказатьnew
2Анна Сидорова+7 916 555-12-34Нужна консультацияprocessed
3Дмитрий К.+7 903 777-88-99Интересует тариф Проnew

Настраиваем Supabase

Регистрация, создание проекта и таблицы — за 5 минут

1

Регистрация

Создай бесплатный аккаунт

🌐
supabase.com

Нажми "Start your project"

→ Войди через GitHub (проще всего) или email

→ Подтверди email если нужно

2

Создай проект

New Project → заполни данные

→ Нажми "New Project"

→ Название: my-landing-db

→ Пароль БД: придумай и запиши!

→ Region: Frankfurt (EU) — ближе к нам

→ Нажми "Create new project" и подожди ~1 минуту

3

Создай таблицу leads

Table Editor → New Table

→ В левом меню нажми Table Editor

→ Нажми "Create a new table"

→ Название: leads

→ Убери галочку "Enable Row Level Security" (для простоты)

→ Добавь колонки:

id — int8, Primary (уже есть)
name — text
phone — text
message — text
status — text, Default: 'new'
created_at — timestamptz, Default: now()

→ Нажми "Save"

4

Скопируй ключи для подключения

Settings → API

→ В левом меню: Project Settings (шестерёнка внизу)

→ Раздел "API"

→ Скопируй два значения:

Project URL:
https://xxxxx.supabase.co
anon / public key:
eyJhbGciOiJIUzI1NiIs...

Эти два значения понадобятся для подключения к серверу!

Шаг 2

Подключаем Supabase

Устанавливаем библиотеку Supabase и сохраняем заявки в базу.

В терминале

npm install @supabase/supabase-js

В Cursor AI Chat

Обнови server.js: 1. Подключи Supabase с моим URL и ключом 2. В POST /api/lead — сохраняй заявку в таблицу leads 3. Выводи ошибку если что-то не так Мой Supabase URL: ВСТАВЬ_URL Мой Supabase Key: ВСТАВЬ_КЛЮЧ

server.js — с Supabase
const { createClient } = require(
  '@supabase/supabase-js'
);

const supabase = createClient(
  'https://xxx.supabase.co',
  'eyJhbGci...'
);

app.post('/api/lead',
  async (req, res) => {
  const { name, phone, message }
    = req.body;

  // Сохраняем в Supabase
  const { data, error } =
    await supabase
      .from('leads')
      .insert([{
        name, phone, message,
        status: 'new'
      }]);

  if (error) {
    return res.status(500)
      .json({ error: error.message });
  }

  res.json({ success: true });
});
Шаг 3

Telegram через сервер

Переносим отправку в Telegram на сервер. Теперь токен не виден клиенту.

В Cursor AI Chat

Добавь в server.js отправку в Telegram после сохранения в Supabase: 1. Используй fetch для отправки на api.telegram.org 2. Токен и Chat ID храни в переменных наверху файла 3. Формат сообщения: «Новая заявка! Имя: ... Телефон: ... Сообщение: ...» 4. Если Telegram не отвечает — не блокируй ответ клиенту Токен: ВСТАВЬ_ТОКЕН Chat ID: ВСТАВЬ_ID

Теперь токен на сервере, клиент его не видит. Безопасно!

server.js — Telegram
const BOT_TOKEN = 'ВАШ_ТОКЕН';
const CHAT_ID = 'ВАШ_CHAT_ID';

async function sendTelegram(lead) {
  const text = `🔔 Новая заявка!
👤 Имя: ${lead.name}
📱 Тел: ${lead.phone}
💬 ${lead.message || '—'}`;

  try {
    await fetch(
      `https://api.telegram.org/
       bot${BOT_TOKEN}/sendMessage`,
      {
        method: 'POST',
        headers: {
          'Content-Type':
            'application/json'
        },
        body: JSON.stringify({
          chat_id: CHAT_ID,
          text: text,
          parse_mode: 'HTML'
        })
      }
    );
  } catch (e) {
    console.error('TG error:', e);
  }
}

// В POST /api/lead после insert:
sendTelegram({ name, phone, message });
Шаг 4

Обновляем лендинг

Меняем fetch в лендинге: вместо api.telegram.org отправляем на наш сервер.

В Cursor AI Chat

В index.html измени отправку формы: Вместо fetch на api.telegram.org теперь отправляй POST на http://localhost:3001/api/lead с JSON-телом {name, phone, message} Убери токен и chat_id из клиентского кода — теперь они на сервере.

Было vs Стало:

api.telegram.org/bot{TOKEN}/sendMessage
localhost:3001/api/lead
index.html — новый fetch
<"text-[#a78bfa]">class="text-[#f472b6]">script>
document.querySelector('form')
  .addEventListener('submit',
    async (e) => {
  e.preventDefault();

  const name =
    e.target.name.value;
  const phone =
    e.target.phone.value;
  const message =
    e.target.message.value;

  const res = await fetch(
    'http://localhost:3001/api/lead',
    {
      method: 'POST',
      headers: {
        'Content-Type':
          'application/json'
      },
      body: JSON.stringify({
        name, phone, message
      })
    }
  );

  const data = await res.json();

  if (data.success) {
    alert('Заявка отправлена!');
    e.target.reset();
  }
});
</"text-[#a78bfa]">class="text-[#f472b6]">script>
Шаг 5

Админ-панель

Простая страница для просмотра заявок и смены статуса

В Cursor AI Chat

Создай admin.html — страницу админ-панели: 1. При загрузке — загружает все заявки из Supabase (fetch GET /api/leads) 2. Показывает таблицу: №, Имя, Телефон, Сообщение, Статус, Действие 3. Статус «Новая» — синий бейдж, «Обработана» — зелёный 4. Кнопка «Обработать» — меняет статус через PATCH /api/leads/:id 5. Фильтры: Все / Новые / Обработанные 6. Тёмная тема как у лендинга Добавь в server.js два новых endpoint: - GET /api/leads — все заявки из Supabase - PATCH /api/leads/:id — обновить статус

localhost:3001/admin.html

Заявки

Всего: 4 | Новых: 3

ВсеНовыеОбработанные
#ИмяТелефонСообщениеСтатус
1Иван Петров+7 999 123-45-67Хочу заказатьНовая
2Анна Сидорова+7 916 555-12-34Нужна консультацияОбработана
3Дмитрий Козлов+7 903 777-88-99Интересует тариф ПроНовая
4Елена Волкова+7 926 333-44-55Когда можете начать?Новая

Тестируем всё!

Полная цепочка от формы до админки

📝Формаимя, телефон
🖥️СерверPOST /api/lead
🗄️Supabaseсохранить в БД
📊Админкаadmin.html
Сервер также ↓
📱Telegramуведомить

Запускаем:

# Терминал 1: сервер
#34d399]">$ cd backend
#34d399]">$ node server.js
Сервер работает на порту 3001

# Терминал 2: лендинг
# Открой index.html в браузере
# или используй Live Server

Проверяем:

1Заполни форму на лендинге
2Нажми «Отправить»
3Увидь «Заявка отправлена!»
4Проверь Telegram — сообщение пришло
5Открой admin.html — заявка в таблице
6Нажми «Обработать» — статус сменился

Что мы построили

Установили Node.js
Создали Express-сервер с API
Зарегистрировались в Supabase
Создали таблицу leads в базе данных
Подключили сохранение заявок
Перенесли Telegram на сервер (безопасно)
Обновили лендинг — fetch на свой сервер
Создали админ-панель с фильтрами
Протестировали всю цепочку

Архитектура нашего приложения:

🌐Лендинг
🖥️Express
🗄️Supabase
📊Админка
Express также ↓
📱Telegram

Поздравляем!

Ты прошёл путь от нуля до полноценного веб-приложения с бэкендом, базой данных и админ-панелью. Всё с помощью вайб-кодинга!