integration: add Playwright, axe and Lighthouse CI gates
Lock SEO, accessibility and crawlability with headless browser checks so regressions fail before a merge instead of after publication. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
13
AGENTS.md
13
AGENTS.md
@@ -42,6 +42,9 @@ This is a bilingual recruiter and B2B portfolio for a software/DevOps engineer.
|
||||
| `npm run format:check` | Prettier check (CI). |
|
||||
| `npm run serve:ssr` | Serve the production SSR bundle. |
|
||||
| `npm run serve:ssr:Portfolio` | Alias of `serve:ssr` for existing tooling. |
|
||||
| `npm run e2e` | Playwright + axe-core against the SSR bundle. |
|
||||
| `npm run e2e:install` | Install the pinned Chromium build. |
|
||||
| `npm run lighthouse` | Production build, then Lighthouse CI. |
|
||||
| `npm run ci` | lint, format:check, test:ci, then build. |
|
||||
|
||||
## Code conventions
|
||||
@@ -99,6 +102,7 @@ German and English are written idiomatically per language, never machine-transla
|
||||
- No `window`, `document`, `navigator`, `localStorage` or `matchMedia` access outside `afterNextRender` or `isPlatformBrowser` guards
|
||||
- Use the injected `DOCUMENT` token when the document element is required (it works on server and browser)
|
||||
- No user-agent sniffing; use CSS media queries for device capability
|
||||
- Exception: `isApplePlatform()` in `src/app/core/platform/browser.ts` may read `navigator.userAgentData?.platform ?? navigator.platform` after hydration, only to label the Command key. There is no CSS media query for that key. It is not used for device capability.
|
||||
- Capability helpers live in `src/app/core/platform/browser.ts` and return conservative defaults on the server
|
||||
- Helpers that use `inject()` must be called from a field initializer or constructor, never from a lifecycle hook or callback, and the resolved value must be stored on the instance
|
||||
- Every addressable route must remain prerenderable
|
||||
@@ -121,8 +125,13 @@ German and English are written idiomatically per language, never machine-transla
|
||||
- Real locale-prefixed URLs
|
||||
- Server-rendered core text
|
||||
- Per-route titles from the content layer
|
||||
- Canonical origin is `SITE_CONFIG.siteOrigin` (`https://antoniolede.de`); every absolute URL in the app and tests is derived from it
|
||||
- Per-route metadata (description, canonical, reciprocal hreflang including `x-default`, Open Graph, Twitter, robots) is written by `SeoService` during SSR and on every client navigation
|
||||
- One JSON-LD `@graph` script per route: Person and ProfessionalService on Home, Service on service routes, CreativeWork per public case on projects, WebPage elsewhere
|
||||
- `public/robots.txt`, `public/sitemap.xml` and `public/llms.txt` stay synchronized with `prerenderablePaths()` via `crawl-assets.spec.ts`
|
||||
- The language switch exposes `hreflang` on the alternate-locale link
|
||||
|
||||
Canonical, hreflang document tags and JSON-LD arrive in the integration phase. The language switch already exposes `hreflang` on the alternate-locale link.
|
||||
Browser binaries, HTML reports, traces and screenshots are not committed (`test-results`, `playwright-report`, `.lighthouseci`).
|
||||
|
||||
## Test checklist
|
||||
|
||||
@@ -136,6 +145,8 @@ A change is not done until:
|
||||
6. Routing and locale contracts still have unit coverage (paths, locale helpers, navigation links)
|
||||
7. No new `window` / `document` / `navigator` reads were added outside an SSR-safe guard
|
||||
8. Placeholder or legal copy was not replaced with invented professional claims
|
||||
9. Crawl files still match `SITE_CONFIG.siteOrigin` and `prerenderablePaths()`
|
||||
10. Playwright (`npm run e2e`) and Lighthouse CI (`npm run lighthouse`) still pass when the change affects public HTML, metadata or chrome
|
||||
|
||||
## Domain boundaries
|
||||
|
||||
|
||||
Reference in New Issue
Block a user