Co-authored-by: Cursor <cursoragent@cursor.com>
Portfolio
Bilingual recruiter and B2B portfolio for Antonio Ledebuhr, a software and DevOps engineer. German is the default language at /. English is the full second version under /en.
This repository is the Angular 21 standalone, zoneless, SSR application that serves both locales from one build.
Prerequisites
- Node.js 22 or newer
- npm 11 or newer (npm 12 prints an engine-compatibility warning on some Node 24 builds; that warning is not an error)
Install
npm install
Scripts
| Script | Description |
|---|---|
npm start |
Start the Angular dev server. |
npm run build |
Production build (default configuration), including SSR and prerendering. |
npm run watch |
Development rebuild on change. |
npm test |
Unit tests in watch mode. |
npm run test:ci |
Unit tests once; exits when finished. |
npm run lint |
Run ESLint. |
npm run lint:fix |
Run ESLint with autofix. |
npm run format |
Format the workspace with Prettier. |
npm run format:check |
Check formatting without writing. |
npm run serve:ssr |
Serve the production SSR bundle from dist/. |
npm run serve:ssr:Portfolio |
Alias of serve:ssr. |
npm run ci |
lint, format check, tests, then production build. |
Local SSR build
npm run build
npm run serve:ssr
The server listens on http://localhost:4000 unless PORT is set. The CV is copied into the browser output at /cv/CV.pdf.
Project structure
src/app/core/ Typed contracts: locale, routing, navigation, content, platform
src/app/features/ One standalone page per route id
src/app/shared/ Reusable UI primitives
src/app/components/ Existing decorative widgets (skills, dot background)
src/styles.scss Design tokens and global primitives
src/_breakpoints.scss Breakpoint map and respond-to mixin
public/ Static SVG assets
Design tokens live in src/styles.scss as CSS custom properties. Content contracts and the placeholder provider live in src/app/core/content. Route ids and locale path tables live in src/app/core/routing.
Contributor and agent conventions are in AGENTS.md.
Legal pages
The Impressum (/impressum, /en/legal-notice) and Datenschutz (/datenschutz, /en/privacy) pages contain unreviewed placeholders. They must be checked by the site owner before publication.