Skip to content

Commit bbced1e

Browse files
committed
refactor: extract reusable SimpleArticle and Offer section components
- Add SimpleArticle component to reduce duplication across article pages - Add ExternalLinkIcon SVG component - Extract offer page sections into dedicated components (Hero, About, Pain, Solution, Advantages, Process, Pricing, FAQ, CTA, Portfolio) - Refactor Article layout with improved i18n and external link support - Simplify article pages to use SimpleArticle wrapper
1 parent 805716b commit bbced1e

23 files changed

Lines changed: 575 additions & 645 deletions
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 3h6v6"/><path d="M10 14 21 3"/><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/></svg>

src/components/SimpleArticle.astro

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
---
2+
import Article from '../layouts/Article.astro';
3+
import ExternalLinkIcon from './ExternalLinkIcon.astro';
4+
5+
interface Props {
6+
title: string;
7+
description: string;
8+
ogTitle: string;
9+
ogDescription: string;
10+
ogImage: string;
11+
ogUrl: string;
12+
articleId: string;
13+
h1: string;
14+
metaRu: string;
15+
metaEn: string;
16+
bodyRu: string;
17+
bodyEn: string;
18+
tech: string;
19+
siteUrl: string;
20+
siteDisplay: string;
21+
screenshotUrl: string;
22+
screenshotAltRu: string;
23+
screenshotAltEn: string;
24+
}
25+
26+
const {
27+
title, description, ogTitle, ogDescription, ogImage, ogUrl,
28+
articleId, h1, metaRu, metaEn,
29+
bodyRu, bodyEn, tech, siteUrl, siteDisplay,
30+
screenshotUrl, screenshotAltRu, screenshotAltEn,
31+
} = Astro.props;
32+
---
33+
34+
<Article
35+
title={title}
36+
description={description}
37+
ogTitle={ogTitle}
38+
ogDescription={ogDescription}
39+
ogImage={ogImage}
40+
ogUrl={ogUrl}
41+
>
42+
<header class="article-header">
43+
<h1 class="article-title" data-i18n={`article_${articleId}_title`} set:html={h1} />
44+
<span data-i18n-content="ru"><p class="article-meta" set:html={metaRu} /></span>
45+
<span data-i18n-content="en" style="display:none"><p class="article-meta" set:html={metaEn} /></span>
46+
</header>
47+
48+
<div class="article-body" data-i18n-content="ru">
49+
<p set:html={bodyRu} />
50+
51+
<p><strong>Технологии:</strong> {tech}</p>
52+
53+
<a class="article-site-link" href={siteUrl} rel="nofollow noopener noreferrer" target="_blank">
54+
<ExternalLinkIcon />
55+
{siteDisplay}
56+
</a>
57+
58+
<a href={siteUrl} rel="nofollow noopener noreferrer" target="_blank"><img src={screenshotUrl} alt={screenshotAltRu} loading="lazy"></a>
59+
</div>
60+
61+
<div class="article-body" data-i18n-content="en" style="display:none">
62+
<p set:html={bodyEn} />
63+
64+
<p><strong>Technologies:</strong> {tech}</p>
65+
66+
<a class="article-site-link" href={siteUrl} rel="nofollow noopener noreferrer" target="_blank">
67+
<ExternalLinkIcon />
68+
{siteDisplay}
69+
</a>
70+
71+
<a href={siteUrl} rel="nofollow noopener noreferrer" target="_blank"><img src={screenshotUrl} alt={screenshotAltEn} loading="lazy"></a>
72+
</div>
73+
</Article>
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<section id="about" class="offer-section px-4 md:px-8 py-16 md:py-24">
2+
<div class="max-w-5xl mx-auto">
3+
<h2 class="text-2xl sm:text-3xl font-bold text-[color:var(--offer-text-primary)] text-center mb-10">Обо мне</h2>
4+
<div class="offer-card">
5+
<div class="grid grid-cols-1 md:grid-cols-[auto_1fr] gap-8 items-center">
6+
<div class="flex justify-center">
7+
<img
8+
src="/images/offer/roman-purtow.png"
9+
alt="Роман Пуртов"
10+
width="200"
11+
height="200"
12+
class="rounded-2xl w-40 h-40 sm:w-48 sm:h-48 object-cover"
13+
/>
14+
</div>
15+
<div>
16+
<h3 class="text-xl font-bold mb-3" style="color: var(--offer-text-primary)">Роман Пуртов</h3>
17+
<div class="offer-card-desc space-y-3">
18+
<p>Создаю сайты с 2018 года — начинал на Тильде и конструкторах, прошёл путь от шаблонов до чистого кода.</p>
19+
<p>С конца 2025 года — выработал собственную методологию быстрой разработки, которая позволяет делать качественные лендинги за дни, а не недели.</p>
20+
<p>Люблю общаться с клиентами — созвоны, голосовые, живой контакт. Для меня важно понять задачу, а не просто «нарисовать макет».</p>
21+
<p>Работаю как самозанятый: договор, акт, чек — всё официально.</p>
22+
</div>
23+
</div>
24+
</div>
25+
</div>
26+
</div>
27+
</section>
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<section id="advantages" class="offer-section px-4 md:px-8 py-16 md:py-24">
2+
<div class="max-w-6xl mx-auto">
3+
<h2 class="text-2xl sm:text-3xl font-bold text-[color:var(--offer-text-primary)] text-center mb-10">Почему этот подход</h2>
4+
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-5">
5+
<div class="offer-card">
6+
<div class="offer-icon mb-3">
7+
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/></svg>
8+
</div>
9+
<h3 class="offer-card-title">Быстро</h3>
10+
<p class="offer-card-desc">Лендинг за 48 часов вместо недель.</p>
11+
</div>
12+
<div class="offer-card">
13+
<div class="offer-icon mb-3">
14+
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/></svg>
15+
</div>
16+
<h3 class="offer-card-title">Чистый код</h3>
17+
<p class="offer-card-desc">Никаких конструкторов. Сайт быстро грузится и отлично ранжируется в поиске.</p>
18+
</div>
19+
<div class="offer-card">
20+
<div class="offer-icon mb-3">
21+
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="5" y="2" width="14" height="20" rx="2" ry="2"/><line x1="12" y1="18" x2="12.01" y2="18"/></svg>
22+
</div>
23+
<h3 class="offer-card-title">Адаптивность</h3>
24+
<p class="offer-card-desc">Идеально выглядит на десктопе, планшете, телефоне.</p>
25+
</div>
26+
<div class="offer-card">
27+
<div class="offer-icon mb-3">
28+
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.778 7.778 5.5 5.5 0 0 1 7.777-7.777zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3m-3.5 3.5L19 4"/></svg>
29+
</div>
30+
<h3 class="offer-card-title">Ваша собственность</h3>
31+
<p class="offer-card-desc">Сайт на вашем хостинге, без привязки к платформе и ежемесячной подписки.</p>
32+
</div>
33+
<div class="offer-card">
34+
<div class="offer-icon mb-3">
35+
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
36+
</div>
37+
<h3 class="offer-card-title">SEO из коробки</h3>
38+
<p class="offer-card-desc">robots.txt, sitemap.xml, быстрая загрузка, правильная разметка.</p>
39+
</div>
40+
<div class="offer-card">
41+
<div class="offer-icon mb-3">
42+
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>
43+
</div>
44+
<h3 class="offer-card-title">Прозрачный процесс</h3>
45+
<p class="offer-card-desc">Вы видите результат на каждом шаге, а не только в конце.</p>
46+
</div>
47+
</div>
48+
</div>
49+
</section>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<section id="cta" class="offer-section px-4 md:px-8 py-16 md:py-24">
2+
<div class="max-w-2xl mx-auto">
3+
<div class="offer-card text-center">
4+
<h2 class="text-2xl sm:text-3xl font-bold mb-3" style="color: var(--offer-text-primary)">Готовы обсудить ваш проект?</h2>
5+
<p class="offer-card-desc mb-8">Оставьте заявку — созвонимся и обсудим задачу. Без обязательств.</p>
6+
<form class="space-y-4 text-left" action="#" method="POST">
7+
<div>
8+
<label for="name" class="offer-label">Имя</label>
9+
<input type="text" id="name" name="name" placeholder="Как к вам обращаться" class="offer-input" required />
10+
</div>
11+
<div>
12+
<label for="contact" class="offer-label">Телефон или Telegram</label>
13+
<input type="text" id="contact" name="contact" placeholder="+7 ... или @username" class="offer-input" required />
14+
</div>
15+
<div>
16+
<label for="about" class="offer-label">Коротко о проекте</label>
17+
<textarea id="about" name="about" rows="3" placeholder="Расскажите, что за проект и какие цели" class="offer-input resize-none"></textarea>
18+
</div>
19+
<button type="submit" class="offer-btn w-full text-center">Оставить заявку</button>
20+
</form>
21+
</div>
22+
</div>
23+
</section>
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
---
2+
const faqs = [
3+
{
4+
question: 'А если мне нужно будет что-то поменять на сайте?',
5+
answer: 'Конечно, после сдачи сайта я остаюсь на связи. Мелкие правки — это быстро. Если вам важно самостоятельно управлять контентом (менять тексты, картинки) — можно подключить удобную админ-панель. По практике: большинству клиентов это не требуется, но такая возможность есть.',
6+
},
7+
{
8+
question: 'Чем это лучше Тильды?',
9+
answer: 'Быстрее загрузка, лучше SEO, нет ежемесячной подписки, нет привязки к платформе. Сайт — ваша собственность.',
10+
},
11+
{
12+
question: 'Как получается так быстро?',
13+
answer: 'Моя методология объединяет этапы, которые в классической разработке идут последовательно. Дизайн сразу создаётся как рабочий сайт, а не отдельно рисуется в Figma и потом переносится в код. Это убирает целый цикл работы.',
14+
},
15+
{
16+
question: 'Какие гарантии по срокам?',
17+
answer: 'Мы фиксируем объём работ и количество итераций на старте. Если укладываемся в рамки — попадаем в заявленное окно. Конкретные сроки зависят от проекта, но типичный лендинг — 2 рабочих дня.',
18+
},
19+
{
20+
question: 'Как оформляется работа?',
21+
answer: 'Договор, акт выполненных работ, чек. Всё официально.',
22+
},
23+
];
24+
---
25+
26+
<section id="faq" class="offer-section px-4 md:px-8 py-16 md:py-24">
27+
<div class="max-w-3xl mx-auto">
28+
<h2 class="text-2xl sm:text-3xl font-bold text-[color:var(--offer-text-primary)] text-center mb-10">Частые вопросы</h2>
29+
30+
{faqs.map(faq => (
31+
<details class="offer-faq">
32+
<summary class="offer-faq-q">
33+
<span>{faq.question}</span>
34+
<svg class="offer-faq-chevron" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg>
35+
</summary>
36+
<div class="offer-faq-a">
37+
<p>{faq.answer}</p>
38+
</div>
39+
</details>
40+
))}
41+
</div>
42+
</section>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<section id="hero" class="offer-section min-h-screen flex items-center justify-center px-4 md:px-8">
2+
<div class="max-w-6xl mx-auto w-full grid grid-cols-1 md:grid-cols-2 gap-8 md:gap-12 items-center">
3+
<div class="order-1 text-center md:text-left">
4+
<h1 class="text-3xl sm:text-4xl lg:text-5xl font-bold leading-tight text-[color:var(--offer-text-primary)] mb-4">
5+
Качественный лендинг за&nbsp;48&nbsp;часов&nbsp;— без&nbsp;конструкторов, без&nbsp;долгостроя
6+
</h1>
7+
<p class="text-base sm:text-lg text-[color:var(--offer-text-muted)] mb-8 leading-relaxed max-w-xl mx-auto md:mx-0">
8+
Собственная методология быстрой разработки на чистом коде. Быстрее студии, качественнее Тильды.
9+
</p>
10+
<a href="#cta" class="offer-btn inline-block">
11+
Обсудить проект
12+
</a>
13+
</div>
14+
<div class="order-2 flex justify-center">
15+
<img
16+
src="/images/offer/roman-purtow.png"
17+
alt="Роман Пуртов"
18+
width="280"
19+
height="280"
20+
class="w-full max-w-xs sm:max-w-sm md:max-w-none md:w-72 lg:w-80 object-contain"
21+
/>
22+
</div>
23+
</div>
24+
</section>
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<section id="pain" class="offer-section px-4 md:px-8 py-16 md:py-24">
2+
<div class="max-w-6xl mx-auto">
3+
<h2 class="text-2xl sm:text-3xl font-bold text-[color:var(--offer-text-primary)] text-center mb-4">Знакомо?</h2>
4+
<p class="text-[color:var(--offer-text-muted)] text-center mb-10 max-w-2xl mx-auto">Большинство предпринимателей сталкиваются с одними и теми же проблемами при создании сайта</p>
5+
<div class="grid grid-cols-1 sm:grid-cols-2 gap-5">
6+
<div class="offer-card">
7+
<div class="text-3xl mb-3">💸</div>
8+
<h3 class="offer-card-title">Студия</h3>
9+
<p class="offer-card-desc">Берёт 200–500 тысяч и делает месяцами. Долго, дорого, куча согласований.</p>
10+
</div>
11+
<div class="offer-card">
12+
<div class="text-3xl mb-3">📋</div>
13+
<h3 class="offer-card-title">Фрилансер на Тильде</h3>
14+
<p class="offer-card-desc">Дешевле, но результат часто шаблонный, а сроки всё равно растягиваются.</p>
15+
</div>
16+
<div class="offer-card">
17+
<div class="text-3xl mb-3">😩</div>
18+
<h3 class="offer-card-title">Сам в конструкторе</h3>
19+
<p class="offer-card-desc">Тратишь время, получается «на троечку», а ведь ты не дизайнер.</p>
20+
</div>
21+
<div class="offer-card">
22+
<div class="text-3xl mb-3">🤖</div>
23+
<h3 class="offer-card-title">Онлайн-генераторы</h3>
24+
<p class="offer-card-desc">Выглядят дёшево, без структуры и без понимания вашего бизнеса.</p>
25+
</div>
26+
</div>
27+
<p class="text-center text-[color:var(--offer-accent-dark)] font-semibold mt-8 text-lg">Нужен другой подход.</p>
28+
</div>
29+
</section>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<section id="portfolio" class="offer-section px-4 md:px-8 py-16 md:py-24">
2+
<div class="max-w-6xl mx-auto">
3+
<h2 class="text-2xl sm:text-3xl font-bold text-[color:var(--offer-text-primary)] text-center mb-10">Портфолио</h2>
4+
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-5">
5+
<div class="offer-card-placeholder">
6+
<span>Скоро</span>
7+
</div>
8+
<div class="offer-card-placeholder">
9+
<span>Скоро</span>
10+
</div>
11+
<div class="offer-card-placeholder">
12+
<span>Скоро</span>
13+
</div>
14+
<div class="offer-card-placeholder hidden sm:flex">
15+
<span>Скоро</span>
16+
</div>
17+
<div class="offer-card-placeholder hidden sm:flex">
18+
<span>Скоро</span>
19+
</div>
20+
<div class="offer-card-placeholder hidden lg:flex">
21+
<span>Скоро</span>
22+
</div>
23+
</div>
24+
</div>
25+
</section>
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<section id="pricing" class="offer-section px-4 md:px-8 py-16 md:py-24">
2+
<div class="max-w-5xl mx-auto">
3+
<h2 class="text-2xl sm:text-3xl font-bold text-[color:var(--offer-text-primary)] text-center mb-10">Тарифы</h2>
4+
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
5+
<!-- Быстрый старт -->
6+
<div class="offer-card flex flex-col">
7+
<h3 class="text-xl font-bold mb-1" style="color: var(--offer-text-primary)">Быстрый старт</h3>
8+
<p class="offer-card-desc mb-4">Лендинг за 48 часов</p>
9+
<div class="text-3xl font-bold text-[color:var(--offer-accent)] mb-6">36 000 <span class="text-base font-normal text-[color:var(--offer-text-muted)]">руб.</span></div>
10+
<ul class="offer-checklist mb-6">
11+
<li>10–12 блоков, адаптив, форма заявки</li>
12+
<li>Политика конфиденциальности, 404</li>
13+
<li>SEO-настройка</li>
14+
<li>Размещение на хостинге</li>
15+
</ul>
16+
<a href="#cta" class="offer-btn mt-auto text-center">Оставить заявку</a>
17+
</div>
18+
<!-- Под ключ -->
19+
<div class="offer-card offer-card--featured flex flex-col">
20+
<div class="text-xs font-semibold text-[color:var(--offer-accent)] uppercase tracking-wider mb-2">Популярный</div>
21+
<h3 class="text-xl font-bold mb-1" style="color: var(--offer-text-primary)">Под ключ</h3>
22+
<p class="offer-card-desc mb-4">Всё из «Быстрого старта» + маркетинг</p>
23+
<div class="text-3xl font-bold text-[color:var(--offer-accent)] mb-6">120 000 <span class="text-base font-normal text-[color:var(--offer-text-muted)]">руб.</span></div>
24+
<ul class="offer-checklist mb-6">
25+
<li>Всё из «Быстрого старта»</li>
26+
<li>Маркетинговое исследование конкурентов</li>
27+
<li>Проработка позиционирования и офферов</li>
28+
<li>Несколько вариантов текстов</li>
29+
<li>5 рабочих дней</li>
30+
</ul>
31+
<a href="#cta" class="offer-btn mt-auto text-center">Оставить заявку</a>
32+
</div>
33+
</div>
34+
<!-- Допродажи -->
35+
<div class="offer-card mt-6 max-w-2xl mx-auto">
36+
<h4 class="font-semibold mb-3" style="color: var(--offer-text-primary)">Дополнительно</h4>
37+
<ul class="offer-card-desc space-y-1">
38+
<li>Админ-панель — от 20 000 руб.</li>
39+
<li>Интеграция с CRM, модуль оплаты — обсуждается отдельно</li>
40+
</ul>
41+
</div>
42+
</div>
43+
</section>

0 commit comments

Comments
 (0)