diff --git a/default.conf b/default.conf
index 28842e7..61e553d 100644
--- a/default.conf
+++ b/default.conf
@@ -1,34 +1,83 @@
+# Loaded by the standard nginx image inside the http context.
+# TLS is terminated by the existing external reverse proxy (Pangolin).
+map $uri $olapka_canonical_path {
+ # Re-evaluate after internal error_page redirects.
+ volatile;
+ default $uri;
+ ~^/index(?:\.html)?/?$ /;
+ ~^/(business-animation|contacts|legal|personal-animation|portfolio|services|social-animation)(?:\.html/?|/)$ /$1;
+}
+
server {
listen 80;
server_name www.olapka.ru;
-
- return 301 https://olapka.ru$request_uri;
+ return 301 https://olapka.ru$olapka_canonical_path$is_args$args;
}
server {
listen 80;
server_name olapka.ru;
-
root /usr/share/nginx/html;
- index index.html;
+ charset utf-8;
+ charset_types text/plain text/css text/markdown application/javascript application/json application/xml image/svg+xml;
- # Отдельная страница ошибки 404
- error_page 404 /404.html;
+ gzip on;
+ gzip_vary on;
+ gzip_proxied any;
+ gzip_min_length 512;
+ gzip_comp_level 5;
+ gzip_types text/plain text/css text/markdown application/javascript application/json application/xml text/xml image/svg+xml;
- # Убираем .html из исходных запросов браузера
- if ($request_uri ~ ^(/[^?]*)\.html(\?.*)?$) {
- return 301 $1$is_args$args;
+ # /404 is an error too, never a successful content page.
+ location = /404 {
+ return 404;
}
- location / {
- try_files $uri $uri.html $uri/ =404;
- }
+ error_page 404 =404 /404.html;
- # Доступ только для внутренней обработки ошибки
location = /404.html {
internal;
}
- # Machine-readable site summaries (UTF-8 Markdown in .txt files).
+
+ # Only return redirects here; no rewrite loops or HTTPS checks behind proxy.
+ if ($uri != $olapka_canonical_path) {
+ return 301 https://olapka.ru$olapka_canonical_path$is_args$args;
+ }
+
+ # try_files serves an existing file in-place, without a client redirect.
+ location = / {
+ try_files /index.html =404;
+ }
+
+ location = /business-animation {
+ try_files /business-animation.html =404;
+ }
+
+ location = /contacts {
+ try_files /contacts.html =404;
+ }
+
+ location = /legal {
+ try_files /legal.html =404;
+ }
+
+ location = /personal-animation {
+ try_files /personal-animation.html =404;
+ }
+
+ location = /portfolio {
+ try_files /portfolio.html =404;
+ }
+
+ location = /services {
+ try_files /services.html =404;
+ }
+
+ location = /social-animation {
+ try_files /social-animation.html =404;
+ }
+
+ # Machine-readable site summaries (UTF-8 Markdown in .txt files).
location ~ ^/llms(?:-full)?\.txt$ {
types { }
default_type text/plain;
@@ -55,4 +104,15 @@ server {
add_header Link '; rel="describedby"';
try_files $uri =404;
}
-}
\ No newline at end of file
+
+ # Revalidate changed assets after one hour (filenames are not versioned).
+ location ~ ^/(?:css|js|img|video)/ {
+ add_header Cache-Control "public, max-age=3600";
+ try_files $uri =404;
+ }
+
+ # Real assets are served normally. Unknown URLs return a real 404.
+ location / {
+ try_files $uri =404;
+ }
+}
diff --git a/default.local.conf b/default.local.conf
new file mode 100644
index 0000000..671fce2
--- /dev/null
+++ b/default.local.conf
@@ -0,0 +1,112 @@
+# Loaded by the standard nginx image inside the http context.
+# Local development only: HTTP on localhost:8080.
+map $uri $olapka_canonical_path {
+ # Re-evaluate after internal error_page redirects.
+ volatile;
+ default $uri;
+ ~^/index(?:\.html)?/?$ /;
+ ~^/(business-animation|contacts|legal|personal-animation|portfolio|services|social-animation)(?:\.html/?|/)$ /$1;
+}
+
+server {
+ listen 80 default_server;
+ server_name localhost 127.0.0.1;
+ root /usr/share/nginx/html;
+ charset utf-8;
+ charset_types text/plain text/css text/markdown application/javascript application/json application/xml image/svg+xml;
+
+ gzip on;
+ gzip_vary on;
+ gzip_proxied any;
+ gzip_min_length 512;
+ gzip_comp_level 5;
+ gzip_types text/plain text/css text/markdown application/javascript application/json application/xml text/xml image/svg+xml;
+
+ # /404 is an error too, never a successful content page.
+ location = /404 {
+ return 404;
+ }
+
+ error_page 404 =404 /404.html;
+
+ location = /404.html {
+ internal;
+ }
+
+ # Only return redirects here; no rewrite loops or HTTPS checks behind proxy.
+ if ($uri != $olapka_canonical_path) {
+ return 301 http://localhost:8080$olapka_canonical_path$is_args$args;
+ }
+
+ # try_files serves an existing file in-place, without a client redirect.
+ location = / {
+ try_files /index.html =404;
+ }
+
+ location = /business-animation {
+ try_files /business-animation.html =404;
+ }
+
+ location = /contacts {
+ try_files /contacts.html =404;
+ }
+
+ location = /legal {
+ try_files /legal.html =404;
+ }
+
+ location = /personal-animation {
+ try_files /personal-animation.html =404;
+ }
+
+ location = /portfolio {
+ try_files /portfolio.html =404;
+ }
+
+ location = /services {
+ try_files /services.html =404;
+ }
+
+ location = /social-animation {
+ try_files /social-animation.html =404;
+ }
+
+ # Machine-readable site summaries (UTF-8 Markdown in .txt files).
+ location ~ ^/llms(?:-full)?\.txt$ {
+ types { }
+ default_type text/plain;
+ charset utf-8;
+ add_header Cache-Control "public, max-age=3600";
+ try_files $uri =404;
+ }
+
+ # Keep the source legal page's noindex policy on its Markdown copy.
+ location = /legal.md {
+ types { }
+ default_type text/markdown;
+ charset utf-8;
+ add_header X-Robots-Tag "noindex, follow";
+ add_header Link '; rel="describedby"';
+ try_files $uri =404;
+ }
+
+ location ~ ^/(index|services|personal-animation|business-animation|social-animation|portfolio|contacts)\.md$ {
+ types { }
+ default_type text/markdown;
+ charset utf-8;
+ add_header Cache-Control "public, max-age=3600";
+ add_header Link '; rel="describedby"';
+ try_files $uri =404;
+ }
+
+ # Revalidate changed assets after one hour (filenames are not versioned).
+ location ~ ^/(?:css|js|img|video)/ {
+ add_header Cache-Control "public, max-age=3600";
+ try_files $uri =404;
+ }
+
+ # Real assets are served normally. Unknown URLs return a real 404.
+ location / {
+ try_files $uri =404;
+ }
+}
diff --git a/docker-compose.local.yml b/docker-compose.local.yml
new file mode 100644
index 0000000..dcf625e
--- /dev/null
+++ b/docker-compose.local.yml
@@ -0,0 +1,8 @@
+services:
+ nginx:
+ image: nginx:stable-alpine
+ ports:
+ - "127.0.0.1:8080:80"
+ volumes:
+ - ./html:/usr/share/nginx/html:ro
+ - ./default.local.conf:/etc/nginx/conf.d/default.conf:ro
diff --git a/html/404.html b/html/404.html
index def5fef..e519198 100644
--- a/html/404.html
+++ b/html/404.html
@@ -5,18 +5,18 @@
@@ -30,10 +30,10 @@
Эта страница улетела из сюжета
Возможно, ссылка устарела или в адресе опечатка. Но ваша история только начинается — вернёмся к ней?
-
Нужна идея? Посмотрите наши работы →
+
Нужна идея? Посмотрите наши работы →
diff --git a/html/business-animation.html b/html/business-animation.html
index 9e25236..09b02ca 100644
--- a/html/business-animation.html
+++ b/html/business-animation.html
@@ -4,22 +4,22 @@
-
+
-
+
Рекламные анимационные ролики для бизнеса — О’ляпка
-
+
-
+
@@ -50,7 +50,7 @@
"telephone": "+79160957383",
"contactType": "customer service",
"availableLanguage": "ru",
- "url": "https://olapka.ru/contacts.html"
+ "url": "https://olapka.ru/contacts"
}
},
{
@@ -65,8 +65,8 @@
},
{
"@type": "WebPage",
- "@id": "https://olapka.ru/business-animation.html#webpage",
- "url": "https://olapka.ru/business-animation.html",
+ "@id": "https://olapka.ru/business-animation#webpage",
+ "url": "https://olapka.ru/business-animation",
"name": "Рекламные анимационные ролики для бизнеса — О’ляпка",
"description": "ИИ-анимация для рекламы, презентации продукта и истории бренда. Объясняем идеи через персонажей и сюжет.",
"inLanguage": "ru",
@@ -77,15 +77,15 @@
"@id": "https://olapka.ru/#organization"
},
"breadcrumb": {
- "@id": "https://olapka.ru/business-animation.html#breadcrumbs"
+ "@id": "https://olapka.ru/business-animation#breadcrumbs"
},
"mainEntity": {
- "@id": "https://olapka.ru/business-animation.html#service"
+ "@id": "https://olapka.ru/business-animation#service"
}
},
{
"@type": "BreadcrumbList",
- "@id": "https://olapka.ru/business-animation.html#breadcrumbs",
+ "@id": "https://olapka.ru/business-animation#breadcrumbs",
"itemListElement": [
{
"@type": "ListItem",
@@ -97,23 +97,23 @@
"@type": "ListItem",
"position": 2,
"name": "Услуги",
- "item": "https://olapka.ru/services.html"
+ "item": "https://olapka.ru/services"
},
{
"@type": "ListItem",
"position": 3,
"name": "Рекламные анимационные ролики для бизнеса",
- "item": "https://olapka.ru/business-animation.html"
+ "item": "https://olapka.ru/business-animation"
}
]
},
{
"@type": "Service",
- "@id": "https://olapka.ru/business-animation.html#service",
+ "@id": "https://olapka.ru/business-animation#service",
"name": "Рекламные анимационные ролики для бизнеса",
"description": "ИИ-анимация для рекламы, презентации продукта и истории бренда. Объясняем идеи через персонажей и сюжет.",
"serviceType": "Рекламные анимационные ролики для бизнеса",
- "url": "https://olapka.ru/business-animation.html",
+ "url": "https://olapka.ru/business-animation",
"provider": {
"@id": "https://olapka.ru/#organization"
}
@@ -123,7 +123,7 @@
Перейти к содержимому
-
Разрешить аналитику для улучшения сайта?
Подробнее
+
Разрешить аналитику для улучшения сайта?
Подробнее
Разрешить Отклонить
@@ -131,26 +131,26 @@
-Главная
-Услуги
+Главная
+Услуги
Рекламные анимационные ролики для бизнеса
@@ -188,31 +188,31 @@
Настройки аналитики