quality: fix heading order + asset caching (0.84.0)

measured the LIVE site with Lighthouse (best-practices 100, seo 100,
agentic-browsing 100; a11y 98, perf 86) and fixed two real flags:
- heading-order: the footer column labels were <h5> following an <h3>
  (skipping h4) — changed to <h4> so the page heading order is sequential;
  a11y 98 -> 100
- caching: every static asset was served with no cache lifetime (0s).
  added nginx cache locations on the amerc.ai vhost (server-side, not in repo):
  /assets/ -> 1y immutable (content-hashed chunks), /scene2d/ -> 30d;
  index.html stays uncached so it always points at the latest assets.
  repeat visitors now serve JS/CSS/images from cache. cache-insight -> PASS
- verified live: a11y 100, heading-order + cache-insight PASS, cache headers
  present on assets and absent on index.html
This commit is contained in:
artheru 2026-06-10 12:02:06 +08:00
parent 40624a2e30
commit 522ce6ec83
4 changed files with 7 additions and 7 deletions

View File

@ -5,7 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="theme-color" content="#0e0a14" />
<meta name="description" content="amerc is the agent mercenary tavern — hire, run, publish, and remotely deliver AI agents across software boundaries. No infrastructure, just skills." />
<meta name="version" content="0.83.0-agentnative" />
<meta name="version" content="0.84.0-quality" />
<link rel="icon" href="/favicon.svg" type="image/svg+xml" />
<link rel="icon" href="/app-192.png" type="image/png" sizes="192x192" />
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />

View File

@ -1,6 +1,6 @@
{
"name": "amerc-site",
"version": "0.83.0-agentnative",
"version": "0.84.0-quality",
"private": true,
"type": "module",
"scripts": {

View File

@ -10,7 +10,7 @@ import { api } from './api.js';
const Menu = ({ size = 20 }) => (<svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" aria-hidden="true"><line x1="3" y1="6" x2="21" y2="6" /><line x1="3" y1="12" x2="21" y2="12" /><line x1="3" y1="18" x2="21" y2="18" /></svg>);
const X = ({ size = 20 }) => (<svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" aria-hidden="true"><line x1="18" y1="6" x2="6" y2="18" /><line x1="6" y1="6" x2="18" y2="18" /></svg>);
const RELEASE = '0.83.0-agentnative';
const RELEASE = '0.84.0-quality';
const NAV = [
{ id: 'home', label: 'Tavern' },
@ -291,17 +291,17 @@ function Footer({ setRoute }) {
<i /> {ok === null ? 'checking…' : ok ? 'All systems operational' : 'Service degraded'}{stats ? ` · ${stats.online} online · ${stats.sessions} live` : ''}
</button>
</div>
<div className="ft-col"><h5>Product</h5>
<div className="ft-col"><h4>Product</h4>
<button onClick={() => setRoute('agents')}>Browse Agents</button>
<button onClick={() => setRoute('mansion')}>Mansion</button>
<button onClick={() => setRoute('booth')}>My Booth</button>
</div>
<div className="ft-col"><h5>Resources</h5>
<div className="ft-col"><h4>Resources</h4>
<a href="https://docs.amerc.ai/">Docs</a>
<button onClick={() => setRoute('changelog')}>Changelog</button>
<a href="/llms.txt" title="amerc for AI agents (llms.txt + WebMCP)">For agents </a>
</div>
<div className="ft-col"><h5>Platform</h5>
<div className="ft-col"><h4>Platform</h4>
<a href="https://git.amerc.ai/">Git</a>
<a href="https://webagent.amerc.ai/health">Webagent</a>
<button onClick={() => setRoute('status')}>Status</button>

View File

@ -1139,7 +1139,7 @@ button {
.ft-status { display: inline-flex; align-items: center; gap: 8px; font-size: 12px; color: #8fe9c0; background: rgba(54,240,176,0.08); border: 1px solid rgba(54,240,176,0.3); border-radius: 16px; padding: 5px 12px; }
.ft-status i { width: 8px; height: 8px; border-radius: 50%; background: #36f0b0; box-shadow: 0 0 0 0 rgba(54,240,176,0.7); animation: ap-pulse 1.8s infinite; }
.ft-status.down { color: #ff9f9f; background: rgba(255,122,140,0.08); border-color: rgba(255,122,140,0.3); } .ft-status.down i { background: #ff7a8c; animation: none; }
.ft-col h5 { font-size: 11px; text-transform: uppercase; letter-spacing: 1px; color: #6f5b8c; margin: 0 0 10px; }
.ft-col h4 { font-size: 11px; text-transform: uppercase; letter-spacing: 1px; color: #6f5b8c; margin: 0 0 10px; }
.ft-col a, .ft-col button { display: block; color: #c3d0e6; font-size: 13px; text-decoration: none; background: none; cursor: pointer; padding: 4px 0; text-align: left; font-family: inherit; }
.ft-col a:hover, .ft-col button:hover { color: #27d8ff; }
.ft-base { max-width: 1080px; margin: 24px auto 0; padding-top: 14px; border-top: 1px solid #140d22; font-size: 11px; color: #5f4f7a; text-align: center; }