Перейти до основного вмісту
megapromotingПоговорімо

Експертиза · Вебсайти

Цей сайт — наша технічна специфікація, включно з вимірюваннями, які нам не на користь.

Ми будуємо сайти з серверним рендерингом, з зображеннями у AVIF і WebP, перевіреними ззовні заголовками безпеки, картою сайту, згенерованою з даних, і перевіркою приймання, що запускається після кожної публікації. Усе це можна оглянути на сторінці, яку ви читаєте.

Вже збудованоNu putem cita un site de client fără acordul lui, dar nu avem nevoie: dovada e chiar pagina asta. Rulează Next.js 16.2.4 cu React 19.1.0, e servită prerandat din cache (`x-nextjs-prerender: 1`, `x-nextjs-cache: HIT`), poartă HSTS cu `preload`, `nosniff`, `SAMEORIGIN`, `Referrer-Policy` și o politică de conținut completă — verificate cu `curl -I` pe 06.09.2026. Harta de site conține 147 de adrese, toate generate din date, nu scrise de mână. A doua implementare, în același depozit: infrastructura formularului — jurnal append-only, sondă publică de sănătate, limitare de rată — și scriptul de acceptare rulat după publicare.

Сайт-візитка має лише один чесний тест: чи можете ви зовні перевірити те, що компанія про нього каже? Саме тому ця сторінка не перелічує технології, а речі, які ви можете самі перевірити командою. Сайт працює на Next.js 16.2.4 і React 19.1.0, а сторінки prerender під час збірки й віддаються з кешу — це видно в заголовках відповіді: `x-nextjs-prerender: 1`, `x-nextjs-cache: HIT`, `s-maxage=31536000`, із вікном у 300 секунд, коли стара сторінка ще може віддаватися під час оновлення.

Серверний рендеринг — не архітектурна вподобаність. Відвідувач із слабким з’єднанням і пошуковий рушій отримують той самий повний HTML, не чекаючи JavaScript. Поверх цього — дисципліна ресурсів: зображення виходять у AVIF і WebP, із кешем на рік; шрифти зберігаються у нас, а не запитуються з зовнішнього сервісу; вісім бібліотек інтерфейсу мають оптимізовані імпорти, щоб не тягнути цілі модулі заради однієї піктограми.

Заголовки безпеки надсилаються з двох місць і перевіряються у реальній відповіді, а не лише в конфігурації: обов’язковий захищений транспорт на два роки з піддоменами та внесенням до списку попереднього завантаження, заборона вгадування типу файлу, обмеження на вбудовування в чужі фрейми, політика реферера, і політика дозволів, що закриває камеру та лишає мікрофон лише для власного походження — бо голосові демонстрації цього потребують і, без цього винятку, браузер мовчки відмовляє.

Остання частина — та, що нас вирізняє, і вона неприємна: ми публікуємо і те, що виміряли в себе погано. Сервер поки що не має Brotli і HTTP/2. Каталог перекладів передається при кожній навігації й коштує приблизно 70 KB стиснених щоразу. Пакет на 443 KB містить чотири каталоги мов, з яких маршрутується лише один. Шрифти також приносять кириличний піднабір, хоча перевірені сторінки не містять жодного кириличного символу. Ці цифри виміряні, записані в репозиторії та в переліку виправлень. Постачальник, який не має таких цифр про власний сайт, або не вимірював, або не хоче казати.

Що входить

Робота, за складовими

Серверний рендеринг, відданий із кешу

Сторінки prerender під час збірки й віддаються як повний HTML, а не будуються в браузері. У реальній відповіді є `x-nextjs-prerender: 1` і `x-nextjs-cache: HIT`, із `cache-control: s-maxage=31536000` і вікном у 300 секунд, коли стара версія ще може віддаватися під час оновлення. Практичний ефект: відвідувач із слабким з’єднанням і crawler отримують той самий вміст в одному й тому самому запиті.

Зображення та шрифти з бюджетом, а не на удачу

Налаштовані формати — AVIF і WebP, із мінімальною тривалістю кешу 31.536.000 секунд — рік — і заголовком `immutable` для статичних файлів, зображень і шрифтів. Шрифти зберігаються в нас під час збірки, а не запитуються з зовнішнього сервісу під час кожного візиту, і відображаються з `swap`, щоб текст з’являвся до завантаження шрифту. Є також пакетний скрипт стиснення з якістю 80 для WebP і 75 для AVIF, щоб джерело не залежало від того, що хтось експортував із графічного редактора.

Заголовки безпеки надсилаються з двох місць і перевіряються у відповіді

З програми: примусовий захищений транспорт 63.072.000 секунд із піддоменами та внесенням до списку попереднього завантаження, `X-Content-Type-Options: nosniff`, `X-Frame-Options: SAMEORIGIN`, `Referrer-Policy: strict-origin-when-cross-origin` і політика дозволів, яка закриває камеру, залишає мікрофон лише для власного джерела та вимикає групування за інтересами. Від вебсервера, окремо: повна політика безпеки вмісту з явним списком дозволених джерел. Під час передавання явно пишеться, що є два місця — інакше наступний, хто щось змінює, шукатиме не там.

Карта сайту, згенерована з даних, а не написана вручну

Карта сайту будується з п’яти джерел — 13 фіксованих адрес, статті, 19 продуктів, 12 послуг і 100 комбінацій послуга × домен — і проходить через фінальну дедуплікацію. Результат: 147 адрес, порахованих і в коді, і у файлі, який віддається у продакшні. Нова сторінка входить автоматично; видалена зникає. Ніхто не підтримує паралельний список, який розсинхронізується за три тижні.

Старі адреси не помирають: 43 постійні перенаправлення

Очищення структури лишає після себе адреси, які хтось зберіг або опублікував. У конфігурації є 43 постійні перенаправлення — 9 гідів до блогу, 20 сирітських статей, 6 перепризначених кейсів і 8 окремих сторінок. Є також 11 сторінок, які перенаправляють зсередини програми; вони коректні функціонально, але дорожчі за правило конфігурації, і це так і вказано в списку виправлень.

Форма — це інфраструктура, а не декор

Запит записується в журнал append-only до спроби доставки, з другим рядком для результату; є публічна перевірка здоров’я, яка показує, чи може лід зараз дістатися до людини; а запити до інтерфейсів обмежені 10 на хвилину, з ключем, узятим із останнього стрибка заголовка перенаправлених адрес, а не з першого — перший надсилає клієнт. Причини записані в коді, а не в окремій документації.

Перевірка приймання після кожної публікації

Скрипт відкриває кожну сторінку продукту, групами по три, і падає, якщо бракує коду 200, якоря запитань, якоря прикладу або канонічної адреси. Потім він перевіряє карту сайту — щоб у ній був кожен продукт і не було мовних варіантів, які не відкриваються — та `robots.txt`, щоб він не блокував ресурси, потрібні для рендерингу. Кожна перевірка відповідає чомусь, що вже ламалося один раз.

Канонічна адреса вирішується один раз, для всього сайту

Канонічна адреса оголошена відносно, в одному місці базового макета, і вирішується для кожного маршруту окремо. Те саме рішення для адреси соціального поширення, яка раніше оголошувала головну сторінку на більшості сторінок. Це рядок коду, який замінює конвенцію, яку кожна нова сторінка мала б пам’ятати сама — і яку, неминуче, не пам’ятає.

Те, що не працює, записано в репозиторії, поруч із кодом

Репозиторій містить файл відомих дефектів, який пояснює, наприклад, чому мовні варіанти в адресі не перемикають мову, чому очевидне рішення робить гірше — під час серверного рендерингу немає ні локального сховища, ні браузера, тож детектор падає на англійську і всі сторінки виходять англійською — і які є два реальні рішення. Ми вважаємо за краще, щоб технічний покупець знайшов обмеження, написане нами, а не виявлене ним.

Як це виглядає

Шлях, крок за кроком.

01

Інвентар адрес і що відбувається зі старими

Перша поставка — це список наявних адрес і рішення для кожної: залишається, перенаправляється або зникає. На цьому сайті вийшло 43 постійні перенаправлення. Це робота, яку всі пропускають, і яка через кілька місяців породжує сторінки помилок у результатах пошуку.

02

Структура вмісту та джерела, з яких він генерується

Сторінки продуктів і послуг будуються з даних, а не з окремих файлів. Звідси походять автоматично згенерована карта сайту, узгоджені канонічні адреси та можливість програмно перевірити, що на кожній сторінці є все необхідне. Ми постачаємо структуру даних, а не лише сторінки, відрендерені з неї.

03

Construirea, cu bugete stabilite înainte de conținut

Від початку ми визначаємо, який формат мають зображення, що кешується і на який строк, що рендериться на сервері та що залишається інтерактивним у браузері. Після цього контент укладається в цей бюджет. Зворотний порядок породжує сайти, які добре виглядають на запуску і ускладнюються з кожною доданою сторінкою.

04

Publicarea cu poartă și verificare de acceptare

Публікація перевіряє вільну пам’ять сервера, запускає аудит безпеки залежностей, збирає з чистого стану і підтверджує, що процес запущено, перш ніж повідомити про успіх. Негайно після цього скрипт приймання відкриває сторінки та перевіряє якорі, канонічні адреси, карту сайту і `robots.txt`. Обидва передаються, у нас не зберігаються.

05

Predarea, cu lista de lipsuri și de măsurători

Ми передаємо код, процедуру публікації, процедуру повернення, адреси здоров’я — і письмовий список того, що не покривається, з цифрами. Для цього сайту список включає відсутність Brotli та HTTP/2 на сервері, вартість каталогу перекладів під час кожної навігації і невикористаний піднабір шрифтів. Ми воліємо, щоб список походив від нас.

Patru straturi verificabile din exterior1HTML prerandat servit din cache2imagini AVIF/WebP și fonturi găzduite local3antete de securitate din aplicație și din serverul web4harta de site și adresele canonice generate din date
Patru straturi verificabile din exterior

Дані

Чого торкаємося, де воно лежить і скільки лишається

Запитання, які ставить кожен, у кого є відповідальний за захист даних, — поставлені тут раніше, ніж їх поставить він.

Datele din formularul de contact
Nume, adresă de e-mail, telefon, companie, serviciu ales, mesaj, pagina de proveniență și prefixul de rețea al vizitatorului. Se scriu într-un jurnal pe serverul propriu, cu drepturi `0700` pe director și `0600` pe fișiere, în afara directorului de versiune. Termen: 24 de luni, aplicat de cod la fiecare scriere, nu de un planificator care poate fi uitat.
Adresa IP, tăiată înainte de a fi scrisă
Зберігається лише мережевий префікс — `/24` для IPv4, `/48` для IPv6 — і зчитується останній hop із заголовка, бо перший надсилає клієнт і він нічого не доводить. Та сама функція використовується і для обмеження швидкості, тож немає другого місця, куди повна адреса могла б потрапити помилково.
Statistici de trafic
Măsurarea trece prin instrumentul de analiză configurat și se activează după consimțământ. Cookie-urile reale au fost verificate empiric pe site-ul live, înainte și după acceptare, iar politica de cookie-uri a fost rescrisă după acea verificare — nu invers. Politica anterioară enumera cookie-uri care nu existau.
Registrul de prelucrări, versionat lângă cod
Кожен тип даних, якого торкається сайт, має запис із метою, підставою, категоріями та строком, у документі, що зберігається в тому самому репозиторії. Коли код змінює строк, документ змінюється в тому самому коміті. Те, що не визначено — наприклад, реальне зберігання в обліковому записі аналітики — позначається явно як елемент для уточнення, а не заявляється як факт.
Ce nu iese din server
Jetoanele de notificare, cheile de furnizor și identificatorii de canal. Sonda de sănătate întoarce exclusiv valori logice, tocmai ca să poată fi interogată de un serviciu extern fără să divulge nimic despre configurație.

Випадок

Ce arată auditul propriului site când îl publici întreg

Ситуація

Після реструктуризації власний сайт здавався в порядку: усі сторінки відповідали 200, панель була зелена. Ми поставили собі запитання, яке ставимо клієнтам: що показує вимірювання, зроблене ззовні, по всіх адресах одразу, а не на головній сторінці?

Що ми збудували

Ми пройшлися прямими запитами по кожній відомій адресі — 249 адрес, 23 колонки на адресу, без відстеження перенаправлень, максимум шість запитів паралельно — і занесли результат у версіонований табличний файл. Поверх нього ми запустили окремі перевірки: реальне стиснення HTML, що передається під час кожної навігації, що містять пакети JavaScript, які шрифти завантажуються, які заголовки кешу та транспорту надає сервер. Кожна цифра була перевірена в реальній відповіді, а не виведена з конфігурації.

Що вийшло

244 адреси відповідають 200, і 5 перенаправляють. 131 сторінка не мала канонічної адреси, а 219 із 244 оголошували головну сторінку як адресу для поширення — обидва випадки тепер виправлені однією лінією в базовому шаблоні, який застосовується до кожного маршруту. Сервер не надає Brotli і не підтримує HTTP/2. Каталог перекладів, 2.268 ключів, передається під час кожної навігації і коштує приблизно 70 KB стисненого щоразу. Пакет 443 KB містить чотири мовні каталоги, з яких лише один є маршрутизованим. Шрифти також приносять кириличний піднабір, хоча перевірені сторінки не містять жодного кириличного символу. Усі цифри, разом із командами, які їх відтворюють, записані в репозиторії.

Чого цей випадок не каже

Це лабораторні вимірювання, зроблені ззовні, прямими запитами. Це не польові дані від реальних відвідувачів, і ми не подаємо їх як такі: метрики сприйманого завантаження не вдалося прочитати в інструменті, який використовували, і вони явно позначені як незміряні. Ми не запускали збірку застосунку під час аудиту, бо кілька людей працювали в одному й тому ж checkout.

Питання

Про що нас питають, перш ніж зателефонувати

Що саме ви використовуєте для побудови?

Next.js 16.2.4 з React 19.1.0 і TypeScript, із Tailwind для стилів та доступними інтерфейсними компонентами на основі примітивів Radix. Сторінки пререндеряться під час збірки й віддаються з кешу — це перевіряється ззовні: заголовки відповіді містять `x-nextjs-prerender: 1` і `x-nextjs-cache: HIT`. Це не список технологій, які ми прочитали; це стек, на якому працює сторінка, яку ви зараз читаєте.

Як самостійно перевірити, що ви кажете про безпеку?

Однією командою: `curl -I https://www.megapromoting.com/servicii`. Ви побачите `strict-transport-security: max-age=63072000; includeSubDomains; preload`, `x-content-type-options: nosniff`, `x-frame-options: SAMEORIGIN`, `referrer-policy: strict-origin-when-cross-origin`, політику дозволів, яка закриває камеру і залишає мікрофон лише для власного походження, а також політику безпеки вмісту з явним списком походжень. Перші п’ять походять із конфігурації застосунку; останню надсилає вебсервер — це два різні місця, і ми так і пишемо під час передачі.

Звідки ви знаєте, що не зіпсували щось під час останньої публікації?

Із сценарію приймання, запущеного після публікації. Він відкриває кожну сторінку продукту і падає, якщо бракує коду 200, якоря питань, якоря прикладу або канонічної адреси; потім перевіряє, що карта сайту містить кожен продукт і не містить мовних варіантів, які не відкриваються, і що `robots.txt` не блокує ресурси рендерингу. Кожна перевірка зі списку відповідає речі, яка вже ламалася. Сценарій передається разом із проєктом — ви можете запускати його і самі.

Ваш сайт швидкий?

Залежить від того, що ви вимірюєте, і в нас є цифри в обидва боки. Добре: сторінки пререндеряться і віддаються з кешу, зображення виходять у AVIF і WebP з кешем на рік, шрифти розміщені локально. Погано, виміряне на власному сайті: сервер не надає Brotli і не підтримує HTTP/2 — запит з `Accept-Encoding: br` отримує несжату відповідь; каталог перекладів передається під час кожної навігації і коштує приблизно 70 KB стисненого щоразу; пакет 443 KB містить чотири мовні каталоги, з яких лише один є маршрутизованим. Я не даю вам лабораторний бал; я даю вам виміряні байти і список виправлень, який з них випливає.

Хто підтримує карту сайту?

Ніхто, і це правильна відповідь. Вона генерується з п’яти джерел даних — фіксованих адрес, статей, продуктів, послуг і комбінацій послуга × домен — і проходить фінальну дедуплікацію. Виходить 147 адрес, та сама цифра в коді й у файлі, який віддається в продакшені. Нова сторінка потрапляє автоматично. Чого бракує сьогодні, щоб сказати прямо: записи не мають дати останньої зміни, а 93 адреси, які можна індексувати, ще не в карті. Вони в списку виправлень, а не приховані.

Ви робите багатомовні сайти?

Тут маю бути точним, бо це найчіткіша межа цього сайту. Перемикання мови з адреси не працює: конфігурація фіксує румунську, тому детектор ніколи не читає параметр. Я записав у репозиторії, чому очевидне рішення гірше — під час серверного рендерингу немає ні локального сховища, ні браузера, тож детектор падає на англійську і всі сторінки виходять англійською — і які є два реальні рішення: маршрути з шляхом, із мовним сегментом, або визначення мови на сервері на кожній сторінці. Перше рекомендоване. Для нового проєкту ми одразу починаємо з маршрутів із шляхом; для існуючого це робота, а не налаштування.

Що відбувається зі старими адресами, коли ви переробляєте сайт?

Інвентаризують і кожному ухвалюють окреме рішення: залишається, перенаправляється назавжди або зникає. Після очищення цього сайту в конфігурації вийшло 43 перенаправлення. Є ще 11 сторінок, які перенаправляють зсередини застосунку — вони працюють, але будують сторінку перед тим, як надіслати відповідь на перенаправлення, що є марною витратою; вони є в списку на перенесення в конфігурацію. Кажу це вам, щоб ви знали, який саме список отримуєте під час передачі.

Як я знаю, що форма справді доставляє?

Ви запитуєте його: `GET /api/health/contact` відповідає 200, якщо lead може зараз дійти до людини, і 503, якщо ні, окремо перевіряючи, що токен каналу сповіщення є дійсним і що журнал запитів можна записати. Відповідь містить лише логічні значення, ніколи не токен. Це існує тому, що саме тут робота одного разу зламалася: токен відкликано, маршрут повертав 500, запити губилися без сліду. Тепер запит записується в журнал перед тим, як починається спроба доставлення.

Що ви не робите?

Ми не обіцяємо позиції в пошуку, відсотки конверсії або показники продуктивності, які не вимірювали на вашому проєкті. Ми не передаємо сайт без списку старих адрес і без процедури повернення. Ми не беремо на себе сторонні платформи, до яких не маємо доступу. І ми не подаємо як готове те, що має відому межу — якщо в мене є межа, ви знайдете її записаною в репозиторії до того, як знайдете її в продакшені.

На чому ґрунтуються твердження вище (15 джерел)
  1. Producția servește pagini prerandate din cache: `x-nextjs-prerender: 1`, `x-nextjs-cache: HIT`, `cache-control: s-maxage=31536000`, `x-nextjs-stale-time: 300`https://www.megapromoting.com/servicii · 2026-09-06
  2. Antete de securitate în răspunsul real: HSTS `max-age=63072000; includeSubDomains; preload`, `nosniff`, `SAMEORIGIN`, `strict-origin-when-cross-origin`, politică de permisiuni cu `microphone=(self)`; plus o politică de securitate a conținutului completă servită de nginx și ABSENTĂ din `next.config.ts`https://www.megapromoting.com/servicii · 2026-09-06

13 з них — це код і файли з наших репозиторіїв. Ми не публікуємо їхні назви чи номери рядків: разом, на одній сторінці, це надто точно описало б, як побудовані системи, які належать не лише нам. Ми проходимо їх разом із вами, у репозиторії, за запитом — перевірка залишається можливою, просто вона відбувається в розмові.

Що вам хотілося б налагодити?

Розкажіть про свій процес. Разом визначимо, що варто збудувати, що можна підключити і як перевіримо результат.

Поговорімо