Files
Portfolio/AGENTS.md

8.2 KiB

AGENTS.md

Contributor and agent guide for this repository. Read this before changing routing, copy, styles, or SSR behaviour.

Purpose

This is a bilingual recruiter and B2B portfolio for a software/DevOps engineer. German is the default language and is served at /. English is the full second version and is served under /en. Every public page exists in both locales.

Architecture

  • Angular 21 standalone components, no NgModules
  • Zoneless change detection
  • Signals for local state
  • Lazy-loaded feature routes
  • SSR with prerendering (@angular/ssr, outputMode: "server")
  • Express host in src/server.ts

Directory map

Path Role
src/app/core/** Contracts, services and tokens. No UI.
src/app/features/** Routed page components, one folder per route.
src/app/shared/** Reusable UI primitives used by multiple features.
src/app/components/** Existing decorative/feature widgets (skills grid, dot background).
public/** Static SVG and public assets copied as-is.
src/styles.scss Global design tokens and primitives. The only place raw brand hex values are defined.
src/_breakpoints.scss Breakpoint map (sm 40rem, md 48rem, lg 64rem, xl 80rem) and the respond-to mixin. Components pull it in with @use 'breakpoints'.

Commands

Script Purpose
npm start Dev server (ng serve).
npm run build Production build (default configuration).
npm run watch Development rebuild on change.
npm test Unit tests in watch mode.
npm run test:ci Unit tests once (--watch=false); must exit.
npm run lint ESLint over the workspace.
npm run lint:fix ESLint with autofix.
npm run format Prettier write.
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 ci lint, format:check, test:ci, then build.

Code conventions

  • Standalone components only
  • inject() over constructor injection for new code
  • Signals over RxJS for local state
  • ChangeDetectionStrategy.OnPush on new components
  • kebab-case file names
  • No any
  • No default exports
  • Templates in separate files

SCSS conventions

  • Global design tokens live only in src/styles.scss as CSS custom properties
  • Components consume var(--...) and never redefine raw hex values
  • Use the documented spacing (--space-1--space-12) and typography (--text-xs--text-3xl) scale
  • Hover-only affordances must be wrapped in @media (hover: hover) and (pointer: fine)
  • All motion must respect prefers-reduced-motion
  • Breakpoints and the respond-to mixin live in src/_breakpoints.scss; do not invent extra breakpoint names
  • Shared glass, layout and focus treatments belong on the global primitives (.glass-surface, .content-container, .stack, .cluster), not copied into component stylesheets
  • Keep component styles under the anyComponentStyle budget (4 kB warn, 8 kB error)

Content rules

All user-facing copy comes from the typed bilingual content layer in src/app/core/content. Never inline marketing or page copy in templates.

Keep the four copy roles as separate fields:

  • headline — the serious heading
  • proof — only a verifiable statement
  • playfulLine — optional wordplay; never a capability claim
  • cta — action label, kept swappable

German and English are written idiomatically per language, never machine-translated word for word.

Claims policy (non-negotiable)

  • No unsupported superlatives
  • No invented references, client names, metrics or certifications
  • Unproven AI, local-LLM or multi-agent capabilities are phrased as an offering or way of working, never as a delivered reference
  • The CV stations HUP, BitWiz and Cybertrading are deliberately excluded from all public pages, cases and timelines
  • The legal pages (Impressum, Datenschutz) contain placeholders that MUST be reviewed by the site owner before publication and must visibly say so

i18n rules

  • German at /, English under /en
  • Every route id exists in both locales
  • New pages are added by extending the route-id table in src/app/core/routing, never by hard-coding paths
  • Do not swap LOCALE_ID; the active locale is AppLocale from LocaleService

SSR rules

  • 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
  • Capability helpers live in src/app/core/platform/browser.ts and return conservative defaults on the server
  • Every addressable route must remain prerenderable

Accessibility checklist

  • Skip link as the first focusable element, targeting #main-content
  • Single h1 per page
  • Landmark elements (header/nav, main, footer)
  • Visible :focus-visible ring
  • Keyboard reachability for every action
  • aria-current on the active nav item
  • At least 4.5:1 text contrast on the base surface
  • Reduced-motion alternatives for animation and smooth scrolling
  • Navigation remains usable in its server-rendered default state (no JS-only menus)

SEO expectations

  • Semantic headings
  • Real locale-prefixed URLs
  • Server-rendered core text
  • Per-route titles from the content layer

Canonical, hreflang document tags and JSON-LD arrive in the integration phase. The language switch already exposes hreflang on the alternate-locale link.

Test checklist

A change is not done until:

  1. npm run lint exits 0
  2. npm run format:check exits 0
  3. npm run test:ci exits 0 with no watcher left running
  4. npm run build exits 0
  5. New or changed routes appear in prerenderablePaths() and are prerendered
  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

Domain boundaries

Branch Owns
Foundation Tooling, tokens, shell, routing and content contracts, SSR safety, test baseline
Content Bilingual copy data and page composition
Signature Systems Map, terminal, dot background and motion
Integration SEO and cross-cutting a11y/performance hardening

Each branch extends the shared contracts instead of duplicating paths or copy. The Content branch replaces placeholder-content.ts and keeps SITE_CONTENT. The Signature branch may replace the dot-background internals but must keep the SSR-safe init/teardown contract.