Add CI lint configs (html-validate, linkinator), fix nav a11y and URL routing

- .htmlvalidate.json with relaxed rules for design-system inline styles
- linkinator.config.json skipping mail, external auth/platform origins
- Fix lint:html npm script quoting for Windows-shell compatibility
- Switch astro build.format to 'directory' so /pricing resolves without MultiViews
- trailingSlash: 'ignore' lets both /pricing and /pricing/ work naturally
- Add aria-label to both <nav> landmarks (Primary, Footer) to satisfy html-validate

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-04-24 17:24:21 +02:00
parent dfb8419b08
commit 04a1bd0aaf
6 changed files with 28 additions and 5 deletions

8
.htmlvalidate.json Normal file
View File

@@ -0,0 +1,8 @@
{
"extends": ["html-validate:recommended"],
"rules": {
"require-sri": "off",
"no-inline-style": "off",
"void-style": "off"
}
}

View File

@@ -4,9 +4,11 @@ import tailwind from '@astrojs/tailwind';
export default defineConfig({ export default defineConfig({
site: 'https://www.cameleer.io', site: 'https://www.cameleer.io',
output: 'static', output: 'static',
trailingSlash: 'never', trailingSlash: 'ignore',
build: { build: {
format: 'file', // 'directory' outputs <page>/index.html so extensionless URLs like /pricing
// resolve natively under Apache without MultiViews or rewrite rules.
format: 'directory',
assets: 'assets', assets: 'assets',
inlineStylesheets: 'auto', inlineStylesheets: 'auto',
}, },

13
linkinator.config.json Normal file
View File

@@ -0,0 +1,13 @@
{
"recurse": true,
"silent": true,
"skip": [
"^https://auth\\.cameleer\\.io",
"^https://platform\\.cameleer\\.io",
"^https://www\\.cameleer\\.io",
"^mailto:",
"^https://ec\\.europa\\.eu"
],
"retry": true,
"concurrency": 10
}

View File

@@ -11,7 +11,7 @@
"astro": "astro", "astro": "astro",
"test": "vitest run", "test": "vitest run",
"test:watch": "vitest", "test:watch": "vitest",
"lint:html": "html-validate 'dist/**/*.html'", "lint:html": "html-validate \"dist/**/*.html\"",
"lint:links": "linkinator dist --recurse --silent", "lint:links": "linkinator dist --recurse --silent",
"lh": "lhci autorun" "lh": "lhci autorun"
}, },

View File

@@ -14,7 +14,7 @@ const year = new Date().getFullYear();
</svg> </svg>
<span class="text-text-muted text-sm">© {year} Cameleer</span> <span class="text-text-muted text-sm">© {year} Cameleer</span>
</div> </div>
<nav class="flex items-center gap-8 text-sm text-text-muted"> <nav class="flex items-center gap-8 text-sm text-text-muted" aria-label="Footer">
<a href="/pricing" class="hover:text-text transition-colors">Pricing</a> <a href="/pricing" class="hover:text-text transition-colors">Pricing</a>
<a href="/imprint" class="hover:text-text transition-colors">Imprint</a> <a href="/imprint" class="hover:text-text transition-colors">Imprint</a>
<a href="/privacy" class="hover:text-text transition-colors">Privacy</a> <a href="/privacy" class="hover:text-text transition-colors">Privacy</a>

View File

@@ -14,7 +14,7 @@ import CTAButtons from './CTAButtons.astro';
</svg> </svg>
<span class="font-sans font-bold text-lg tracking-tight text-text group-hover:text-accent transition-colors">Cameleer</span> <span class="font-sans font-bold text-lg tracking-tight text-text group-hover:text-accent transition-colors">Cameleer</span>
</a> </a>
<nav class="flex items-center gap-8 text-sm"> <nav class="flex items-center gap-8 text-sm" aria-label="Primary">
<a href="/pricing" class="text-text-muted hover:text-text transition-colors">Pricing</a> <a href="/pricing" class="text-text-muted hover:text-text transition-colors">Pricing</a>
</nav> </nav>
<CTAButtons size="md" /> <CTAButtons size="md" />