feat: редизайн 404 страницы по образцу hhivp + обновить CLAUDE.md/README
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
69
CLAUDE.md
Normal file
69
CLAUDE.md
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
# CLAUDE.md — sag24-website
|
||||||
|
|
||||||
|
Инструкции для Claude при работе с этим проектом.
|
||||||
|
|
||||||
|
## Язык
|
||||||
|
|
||||||
|
Всегда отвечать на **русском**.
|
||||||
|
|
||||||
|
## Всё через репозиторий
|
||||||
|
|
||||||
|
Все изменения — только через git репозиторий, если явно не сказано иное. Никогда не копировать файлы напрямую на сервер (scp/rsync/etc).
|
||||||
|
|
||||||
|
## Деплой — ОБЯЗАТЕЛЬНО после каждого изменения
|
||||||
|
|
||||||
|
После любых изменений в коде — деплоить самостоятельно, без ожидания команды:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Локально: commit + push
|
||||||
|
git add <файлы> && git commit -m "..." && git push
|
||||||
|
|
||||||
|
# 2. На сервере: pull + build
|
||||||
|
ssh -i ~/.ssh/id_ed25519_hhivp striker@str-u-01.striker.su 'cat <<XEOF | sudo -S bash
|
||||||
|
Gh_lpx2018!
|
||||||
|
cd /opt/www/sag24.ru/repo && git pull && npm run deploy
|
||||||
|
XEOF'
|
||||||
|
```
|
||||||
|
|
||||||
|
- `.git` принадлежит root — `git pull` требует sudo
|
||||||
|
- `npm run deploy` = `next build` (→ `../public_html`) + `indexnow.mjs`
|
||||||
|
|
||||||
|
## Задачи Singularity
|
||||||
|
|
||||||
|
Проект: **САГ** `P-a41aa057-5401-4ae5-843c-439381fdd7f2`
|
||||||
|
|
||||||
|
При работе — создавать/обновлять/закрывать задачи в Singularity:
|
||||||
|
- Создавать задачу до или в процессе работы
|
||||||
|
- Закрывать (`complete: 1`) сразу после выполнения
|
||||||
|
- Добавлять заметку с деталями
|
||||||
|
|
||||||
|
## Стек
|
||||||
|
|
||||||
|
- Next.js 15, TypeScript, App Router, static export
|
||||||
|
- Tailwind CSS v3 — конфиг `tailwind.config.js` (НЕ `.ts`!)
|
||||||
|
- i18n через `[lang]` сегмент: `/ru/...`, `/en/...`
|
||||||
|
- Контент: `src/locales/ru.ts`, `src/locales/en.ts`
|
||||||
|
|
||||||
|
## Структура страниц
|
||||||
|
|
||||||
|
```
|
||||||
|
/ru/ → Главная
|
||||||
|
/ru/uslugi/ → Каталог + /[slug]/ (8 услуг)
|
||||||
|
/ru/about/ → О компании
|
||||||
|
/ru/clients/ → Клиенты
|
||||||
|
/ru/partners/ → Партнёры
|
||||||
|
/ru/faq/ → FAQ
|
||||||
|
/ru/kontakty/ → Контакты
|
||||||
|
```
|
||||||
|
|
||||||
|
## SEO
|
||||||
|
|
||||||
|
- BreadcrumbList JSON-LD на всех страницах — `src/lib/breadcrumbs.ts`
|
||||||
|
- generateMetadata на каждой странице с canonical + hreflang
|
||||||
|
- После деплоя IndexNow отправляется автоматически
|
||||||
|
|
||||||
|
## Известные ограничения
|
||||||
|
|
||||||
|
- Static export — API routes не работают; форма идёт на `/api/contact.php` (PHP)
|
||||||
|
- `trailingSlash: true` — все URL заканчиваются на `/`
|
||||||
|
- Turnstile SITE_KEY: `0x4AAAAAACrQS-dAb7E9RGPQ`
|
||||||
53
README.md
53
README.md
@@ -1,3 +1,54 @@
|
|||||||
# sag24-website
|
# sag24-website
|
||||||
|
|
||||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD> sag24.ru <EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
Сайт sag24.ru — IT-аутсорсинг «Сисадмингрупп» (Пушкино, МО).
|
||||||
|
|
||||||
|
## Стек
|
||||||
|
|
||||||
|
- **Next.js 15** + TypeScript + App Router
|
||||||
|
- **Static export** (`output: 'export'`, `trailingSlash: true`)
|
||||||
|
- **Tailwind CSS v3** — конфиг: `tailwind.config.js` (не .ts!)
|
||||||
|
- **i18n**: `[lang]` сегмент (`/ru/...`, `/en/...`)
|
||||||
|
- **Шрифт**: Manrope (`next/font/google`)
|
||||||
|
|
||||||
|
## Страницы
|
||||||
|
|
||||||
|
```
|
||||||
|
/ru/ → Главная
|
||||||
|
/ru/uslugi/ → Каталог услуг
|
||||||
|
/ru/uslugi/[slug]/ → 8 страниц услуг
|
||||||
|
/ru/about/ → О компании
|
||||||
|
/ru/clients/ → Клиенты
|
||||||
|
/ru/partners/ → Партнёры
|
||||||
|
/ru/faq/ → FAQ
|
||||||
|
/ru/kontakty/ → Контакты
|
||||||
|
/en/... → Аналогично
|
||||||
|
```
|
||||||
|
|
||||||
|
## Деплой
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Локально:
|
||||||
|
git add . && git commit -m "..." && git push
|
||||||
|
|
||||||
|
# На сервере (str-u-01.striker.su):
|
||||||
|
ssh -i ~/.ssh/id_ed25519_hhivp striker@str-u-01.striker.su 'cat <<XEOF | sudo -S bash
|
||||||
|
Gh_lpx2018!
|
||||||
|
cd /opt/www/sag24.ru/repo && git pull && npm run deploy
|
||||||
|
XEOF'
|
||||||
|
```
|
||||||
|
|
||||||
|
`npm run deploy` = `BUILD_DIR=../public_html next build && node scripts/indexnow.mjs`
|
||||||
|
|
||||||
|
После деплоя автоматически отправляется уведомление в IndexNow (Yandex + api.indexnow.org).
|
||||||
|
|
||||||
|
## Локали
|
||||||
|
|
||||||
|
`src/locales/ru.ts` и `en.ts` — весь текстовый контент.
|
||||||
|
|
||||||
|
## SEO
|
||||||
|
|
||||||
|
- GA4: G-C9J0D8FFH3
|
||||||
|
- Yandex.Metrika: 97525679
|
||||||
|
- IndexNow key: 40c65b722891b81d944f2c3fea6cab95
|
||||||
|
- BreadcrumbList JSON-LD на всех страницах (`src/lib/breadcrumbs.ts`)
|
||||||
|
- sitemap.xml: 36 URLs
|
||||||
|
|||||||
@@ -1,32 +1,82 @@
|
|||||||
import type { Metadata } from 'next'
|
'use client'
|
||||||
import Link from 'next/link'
|
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
import Link from 'next/link'
|
||||||
title: 'Страница не найдена — Сисадмингрупп',
|
import { usePathname } from 'next/navigation'
|
||||||
description: 'Запрошенная страница не существует.',
|
import { Home, Wrench, Mail, ArrowLeft } from 'lucide-react'
|
||||||
robots: { index: false },
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function NotFound() {
|
export default function NotFound() {
|
||||||
|
const pathname = usePathname()
|
||||||
|
const lang = pathname?.startsWith('/en') ? 'en' : 'ru'
|
||||||
|
|
||||||
|
const t = lang === 'en' ? {
|
||||||
|
subtitle: 'Page Not Found',
|
||||||
|
description: 'The page you are looking for does not exist or has been moved.',
|
||||||
|
home: 'Go Home',
|
||||||
|
services: 'Our Services',
|
||||||
|
contact: 'Contact Us',
|
||||||
|
back: 'Go Back',
|
||||||
|
} : {
|
||||||
|
subtitle: 'Страница не найдена',
|
||||||
|
description: 'Запрошенная страница не существует или была перемещена.',
|
||||||
|
home: 'На главную',
|
||||||
|
services: 'Услуги',
|
||||||
|
contact: 'Контакты',
|
||||||
|
back: 'Назад',
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<html lang="ru">
|
<div className="min-h-screen bg-gradient-to-br from-slate-900 via-blue-950 to-slate-900 flex items-center justify-center px-4 relative overflow-hidden">
|
||||||
<body style={{ margin: 0, fontFamily: 'sans-serif', background: '#f8fafc' }}>
|
{/* Grid pattern */}
|
||||||
<div style={{ minHeight: '100vh', display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '2rem' }}>
|
<div className="absolute inset-0 opacity-5"
|
||||||
<div style={{ textAlign: 'center', maxWidth: '480px' }}>
|
style={{ backgroundImage: 'linear-gradient(#fff 0.5px, transparent 0.5px), linear-gradient(90deg, #fff 0.5px, transparent 0.5px)', backgroundSize: '4rem 4rem' }} />
|
||||||
<div style={{ fontSize: '6rem', fontWeight: 700, color: '#2563eb', lineHeight: 1 }}>404</div>
|
|
||||||
<h1 style={{ fontSize: '1.5rem', fontWeight: 700, color: '#0f172a', margin: '1rem 0 0.5rem' }}>
|
{/* Glow orbs */}
|
||||||
Страница не найдена
|
<div className="absolute top-1/4 left-1/4 w-96 h-96 bg-blue-500/10 rounded-full blur-3xl" />
|
||||||
</h1>
|
<div className="absolute bottom-1/4 right-1/4 w-96 h-96 bg-blue-700/10 rounded-full blur-3xl" />
|
||||||
<p style={{ color: '#64748b', marginBottom: '2rem' }}>
|
|
||||||
Запрошенная страница не существует или была перемещена.
|
<div className="relative z-10 text-center max-w-2xl mx-auto">
|
||||||
</p>
|
{/* 404 */}
|
||||||
<Link href="/ru/"
|
<div className="text-[10rem] sm:text-[14rem] font-bold leading-none select-none"
|
||||||
style={{ display: 'inline-block', padding: '0.75rem 2rem', background: '#2563eb', color: '#fff', borderRadius: '0.5rem', textDecoration: 'none', fontWeight: 600 }}>
|
style={{
|
||||||
На главную
|
background: 'linear-gradient(135deg, #60a5fa, #3b82f6, #60a5fa)',
|
||||||
|
backgroundSize: '200% auto',
|
||||||
|
WebkitBackgroundClip: 'text',
|
||||||
|
WebkitTextFillColor: 'transparent',
|
||||||
|
backgroundClip: 'text',
|
||||||
|
}}>
|
||||||
|
404
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h1 className="text-2xl sm:text-3xl font-bold text-white mt-2 mb-4">{t.subtitle}</h1>
|
||||||
|
<p className="text-slate-400 text-lg mb-10">{t.description}</p>
|
||||||
|
|
||||||
|
{/* Buttons */}
|
||||||
|
<div className="flex flex-wrap justify-center gap-3 mb-8">
|
||||||
|
<Link href={`/${lang}/`}
|
||||||
|
className="inline-flex items-center gap-2 px-6 py-3 bg-blue-600 hover:bg-blue-500 text-white font-semibold rounded-lg transition-colors">
|
||||||
|
<Home size={18} />
|
||||||
|
{t.home}
|
||||||
|
</Link>
|
||||||
|
<Link href={`/${lang}/uslugi/`}
|
||||||
|
className="inline-flex items-center gap-2 px-6 py-3 bg-slate-800 hover:bg-slate-700 text-white font-semibold rounded-lg border border-slate-700 transition-colors">
|
||||||
|
<Wrench size={18} />
|
||||||
|
{t.services}
|
||||||
|
</Link>
|
||||||
|
<Link href={`/${lang}/kontakty/`}
|
||||||
|
className="inline-flex items-center gap-2 px-6 py-3 bg-slate-800 hover:bg-slate-700 text-white font-semibold rounded-lg border border-slate-700 transition-colors">
|
||||||
|
<Mail size={18} />
|
||||||
|
{t.contact}
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Back */}
|
||||||
|
<button
|
||||||
|
onClick={() => window.history.back()}
|
||||||
|
className="inline-flex items-center gap-2 text-slate-400 hover:text-blue-400 transition-colors text-sm">
|
||||||
|
<ArrowLeft size={16} />
|
||||||
|
{t.back}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user