fix(i18n,404,nginx): broken-windows batch B2 from the external review
Deploy / build (push) Successful in 3m59s
Deploy / build (push) Successful in 3m59s
All items measured before/after with curl, on the origin and through Cloudflare: - /posts/zh/ answered 403 (directory with no index) -> nginx 301 to the new archive - /zh/posts/ 404'd -> new src/pages/zh/posts/index.astro (build 163 -> 165 pages) - ZH nav pointed "关于" at /zh/ and "文章" at /zh/ -> /zh/about/ and /zh/posts/ - og:locale was "en" on every Chinese page -> zh_CN, plus og:locale:alternate on both languages (EN pages now advertise zh_CN as well) - hreflang "zh" -> "zh-Hans"; <html lang> on ZH pages -> zh-Hans - no 404 page existed -> src/pages/404.astro, served by nginx with a 404 status so crawlers skip it, offering search + archive + the 3 newest posts - JSON-LD Person gained worksFor (Hoelee Enterprise); image still omitted until the author photo exists rather than pointing at a placeholder nginx: config moved from the stock image file to a host bind mount (/mnt/user/docker/nginx-hoelee-blog/conf.d/default.conf, Portainer stack 247 on endpoint 3), validated with nginx -t in a throwaway container before the redeploy. It also sets /_astro/* to immutable 1-year (hashed names) and HTML to must-revalidate; unhashed /og/*.png and /banners/*.png keep the default TTL on purpose. Note: the public HSTS and 16-day asset TTL come from Cloudflare zone settings, not from this nginx. Docs: ops-runbook.md (the nginx layer + why each rule), project-state.md (B2 entry and the two open Cloudflare items my token cannot write).
This commit is contained in:
1 parent
831d440661
commit
874c434576
6 files changed
+160
-6
No files matched your search
@@ -0,0 +1,61 @@
|
||||
---
|
||||
import BaseLayout from '../layouts/BaseLayout.astro';
|
||||
import { getCollection } from 'astro:content';
|
||||
import { isEn } from '../lib/lang';
|
||||
import { sortForListing } from '../lib/sort';
|
||||
|
||||
// Static 404. nginx serves it with `error_page 404 /404.html`, so the status code
|
||||
// stays 404 (crawlers do not index it) while the visitor gets a way forward.
|
||||
// Before this existed, a broken link showed nginx's bare default page.
|
||||
const latest = sortForListing(await getCollection('posts', isEn)).slice(0, 3);
|
||||
const fmt = (d: Date) =>
|
||||
d.toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' });
|
||||
---
|
||||
|
||||
<BaseLayout
|
||||
title="404 — Page Not Found — Mr Hoelee"
|
||||
description="That URL does not exist on this site. Search the posts or browse the archive."
|
||||
>
|
||||
<h1>404 — container exited (code 1)</h1>
|
||||
<p>
|
||||
There is no page at this address. It may have been renamed, or the link that sent
|
||||
you here may be wrong. Nothing is broken on your side.
|
||||
</p>
|
||||
|
||||
<p class="notfound-actions">
|
||||
<button id="search-cta" class="notfound-btn" type="button">⌕ Search the posts</button>
|
||||
<a href="/posts/">Browse all posts</a>
|
||||
<span class="sep">·</span>
|
||||
<a href="/categories/">Categories</a>
|
||||
<span class="sep">·</span>
|
||||
<a href="/zh/">中文</a>
|
||||
</p>
|
||||
|
||||
<h2>Recent posts</h2>
|
||||
<ul class="post-list">
|
||||
{latest.map((p) => (
|
||||
<li class="post-row notfound-row">
|
||||
<div class="body">
|
||||
<a href={`/posts/${p.slug}/`}><h2>{p.data.title}</h2></a>
|
||||
<div class="meta">
|
||||
<time datetime={p.data.pubDate.toISOString()}>{fmt(p.data.pubDate)}</time>
|
||||
<span class="sep">·</span>
|
||||
<a class="tag" href={`/categories/${p.data.category}/`}>{p.data.category}</a>
|
||||
</div>
|
||||
<p>{p.data.description}</p>
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
<script>
|
||||
// The search overlay is mounted on every page by BaseLayout; its trigger is the
|
||||
// ⌕ button in the header (also bound to Ctrl/Cmd+K there). Route this page's
|
||||
// button to the same overlay instead of growing a second search implementation.
|
||||
const cta = document.getElementById('search-cta');
|
||||
cta?.addEventListener('click', () => {
|
||||
const toggle = document.getElementById('search-toggle');
|
||||
if (toggle) toggle.click();
|
||||
});
|
||||
</script>
|
||||
</BaseLayout>
|
||||
Reference in new issue
Block a user