chore: archive completed OpenSpec changes

Archive all 6 deployed changes following OpenSpec workflow:
- add-minimal-hugo-site → hugo-site spec
- add-multilingual-support → internationalization spec
- migrate-site-content → content-migration + image-assets specs
- add-custom-bootstrap-styling → styling spec
- add-cv-page → content-management spec
- simple-deployment → deployment spec

All changes moved to archive/ with 2025-10-30 date prefix.
Created 7 capability specs reflecting deployed functionality.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-10-30 17:22:03 +01:00
co-authored by Claude
parent 937e6a4ded
commit adbee2c655
29 changed files with 637 additions and 0 deletions
@@ -0,0 +1,18 @@
## Why
The site currently uses Bootstrap 5.3.2 from CDN with default styling. To establish a unique visual identity and brand consistency, we need the ability to customize Bootstrap variables (font sizes, colors, spacing) and add custom styles without modifying the core framework.
## What Changes
- Add Hugo SCSS/SASS processing pipeline using Hugo Pipes
- Create custom SCSS file structure for Bootstrap variable overrides and custom styles
- Maintain Bootstrap CSS from CDN for core framework
- Compile custom styles to supplement Bootstrap defaults
- Enable customization of heading font sizes, link colors, and other design tokens
## Impact
- Affected specs: `styling` (new capability)
- Affected code:
- `layouts/_default/baseof.html` - Update to include compiled custom CSS
- `assets/scss/` - New directory for SCSS files
- `hugo.toml` - May need configuration for SCSS processing
- No breaking changes to existing functionality
- Performance: Minimal impact, adds one additional CSS file (~few KB)
@@ -0,0 +1,65 @@
## ADDED Requirements
### Requirement: SCSS Processing Pipeline
The system SHALL process SCSS files using Hugo Pipes to generate custom CSS that supplements Bootstrap's CDN-provided styles.
#### Scenario: SCSS compilation on build
- **WHEN** Hugo builds the site
- **THEN** SCSS files in `assets/scss/` are compiled to CSS
- **AND** the compiled CSS is fingerprinted for cache busting
- **AND** the resulting CSS file is included in the HTML output
#### Scenario: Development mode with live reload
- **WHEN** running Hugo in development mode (hugo server)
- **THEN** SCSS changes trigger automatic recompilation
- **AND** the browser live-reloads with updated styles
### Requirement: Bootstrap Variable Customization
The system SHALL allow customization of Bootstrap design tokens through SCSS variables without modifying the CDN-provided Bootstrap CSS.
#### Scenario: Override heading font sizes
- **WHEN** custom heading sizes are defined in SCSS variables
- **THEN** the compiled CSS applies these sizes to heading elements
- **AND** the Bootstrap CDN CSS is loaded first (base styles)
- **AND** custom CSS is loaded after (overrides)
#### Scenario: Override link colors
- **WHEN** custom link colors are defined in SCSS variables
- **THEN** links across the site use the custom colors
- **AND** link hover states use appropriate custom colors
#### Scenario: Override spacing scale
- **WHEN** custom spacing values are defined
- **THEN** elements using those spacing classes reflect the custom values
### Requirement: Custom Style Organization
The system SHALL organize custom styles in a maintainable SCSS file structure following Hugo and SASS best practices.
#### Scenario: Main SCSS entry point
- **WHEN** Hugo processes SCSS
- **THEN** a single main SCSS file serves as the entry point
- **AND** this file imports Bootstrap variable overrides
- **AND** this file imports custom component styles
- **AND** this file imports custom utility styles
#### Scenario: Modular SCSS files
- **WHEN** developers add new custom styles
- **THEN** styles can be organized into separate partial files
- **AND** partial files are imported into the main SCSS file
- **AND** file naming follows SCSS conventions (e.g., `_variables.scss`, `_custom.scss`)
### Requirement: CSS Output Integration
The system SHALL integrate compiled custom CSS into the base layout template alongside Bootstrap CDN CSS.
#### Scenario: CSS load order
- **WHEN** a page is rendered
- **THEN** Bootstrap CDN CSS loads first
- **AND** custom compiled CSS loads second
- **AND** CSS files include integrity hashes where applicable
- **AND** the custom CSS file path includes a fingerprint for cache busting
#### Scenario: Production build optimization
- **WHEN** building for production
- **THEN** SCSS is compiled with minification
- **AND** the output CSS is optimized for file size
- **AND** source maps are not included in production builds
@@ -0,0 +1,30 @@
## 1. SCSS Infrastructure Setup
- [x] 1.1 Create `assets/scss/` directory structure
- [x] 1.2 Create main SCSS entry file `assets/scss/main.scss`
- [x] 1.3 Create Bootstrap variable overrides file `assets/scss/_variables.scss`
- [x] 1.4 Create custom styles file `assets/scss/_custom.scss`
## 2. Hugo Pipes Integration
- [x] 2.1 Update `layouts/_default/baseof.html` to process SCSS with Hugo Pipes
- [x] 2.2 Configure SCSS compilation with `css.Sass` (updated from deprecated `resources.ToCSS`)
- [x] 2.3 Add fingerprinting for cache busting with `resources.Fingerprint`
- [x] 2.4 Ensure correct CSS load order (Bootstrap CDN first, then custom)
## 3. Initial Custom Styles
- [x] 3.1 Add heading font size customizations to `_variables.scss`
- [x] 3.2 Add link color customizations to `_variables.scss`
- [x] 3.3 Test variable overrides render correctly
- [x] 3.4 Verify styles cascade properly over Bootstrap defaults
## 4. Testing & Validation
- [x] 4.1 Test SCSS compilation in development mode (hugo server)
- [x] 4.2 Test production build (hugo build)
- [x] 4.3 Verify live reload works with SCSS changes
- [x] 4.4 Check generated CSS file size and performance (154 bytes minified)
- [x] 4.5 Validate CSS output is minified in production
- [x] 4.6 Test in multiple browsers for consistency
## 5. Documentation
- [x] 5.1 Document SCSS file structure and conventions
- [x] 5.2 Add examples of how to customize Bootstrap variables
- [x] 5.3 Document the CSS compilation and caching strategy
@@ -0,0 +1,18 @@
# Add CV Page
## Why
The site currently lacks a dedicated curriculum vitae page for HR professionals and recruiters. A CV page with secure download instructions and a navigation menu entry will make the site more complete and professional, enabling visitors to easily access professional credentials.
## What Changes
- Add new CV content page at `/content/cv.md` with German text explaining secure CV download process
- Add CV navigation link to site menu configuration in `hugo.toml`
- Content will explain Tresorit secure download process and email verification requirement
- Page will follow existing single.html layout pattern with centered, readable content
## Impact
- Affected specs: `content-management` (new capability)
- Affected code:
- `/content/cv.md` (new file)
- `/hugo.toml` (menu configuration)
- `/layouts/partials/nav.html` (already supports menu items via iteration)
- User-facing: New "Lebenslauf" navigation link and dedicated CV page
@@ -0,0 +1,37 @@
# Content Management
## ADDED Requirements
### Requirement: CV Page Content
The site SHALL provide a dedicated curriculum vitae page that explains how to securely download the CV document and request additional materials.
#### Scenario: CV page displays download instructions
- **WHEN** a visitor navigates to `/cv/` or clicks "Lebenslauf" in navigation
- **THEN** the page displays a clear explanation of the Tresorit download process
- **AND** the page includes the secure download link
- **AND** the page mentions email verification is required
- **AND** the page explains that certificates and references are available upon personal request
#### Scenario: CV page uses German language
- **WHEN** the CV page is rendered
- **THEN** all text is displayed in German
- **AND** the tone is professional and suitable for HR personnel and recruiters
#### Scenario: CV page follows site layout
- **WHEN** the CV page is rendered
- **THEN** it uses the standard single.html layout
- **AND** content is centered and readable
- **AND** it includes the site header and footer
### Requirement: CV Navigation Link
The site navigation SHALL include a link to the CV page.
#### Scenario: Navigation menu shows CV link
- **WHEN** a visitor views any page on the site
- **THEN** the navigation menu includes a "Lebenslauf" link
- **AND** the link points to `/cv/`
- **AND** the link follows the same styling as other navigation items
#### Scenario: CV link active state
- **WHEN** a visitor is on the CV page
- **THEN** the "Lebenslauf" navigation link shows active state styling
@@ -0,0 +1,27 @@
## 1. Content Creation
- [x] 1.1 Create `content/cv.md` with German CV page content
- [x] 1.2 Add front matter with title "Lebenslauf" and appropriate metadata
- [x] 1.3 Write clear instructions for Tresorit download process
- [x] 1.4 Include secure download link (https://web.tresorit.com/l/khkGf#UBmRnKs_3dkUTZRwtbbdUQ)
- [x] 1.5 Mention email verification requirement
- [x] 1.6 Explain that certificates and references are available on personal request
## 2. Navigation Configuration
- [x] 2.1 Update `hugo.toml` to add CV page to main menu
- [x] 2.2 Configure menu item with German label "Lebenslauf"
- [x] 2.3 Set appropriate menu weight for ordering
- [x] 2.4 Verify menu link points to `/cv/`
## 3. Navigation Template Enhancement
- [x] 3.1 Review `layouts/partials/nav.html` for active state handling
- [x] 3.2 Ensure CV link shows active state when on CV page
- [x] 3.3 Test navigation styling consistency
## 4. Testing & Validation
- [x] 4.1 Test CV page renders correctly in development mode
- [x] 4.2 Verify navigation link appears and points to correct URL
- [x] 4.3 Test active state styling on CV page
- [x] 4.4 Verify Tresorit link is clickable and correct
- [x] 4.5 Check responsive layout on mobile devices (tested via generated HTML - Bootstrap responsive classes in place)
- [x] 4.6 Validate German language and professional tone
- [x] 4.7 Test production build
@@ -0,0 +1,118 @@
## Context
Converting an existing static HTML website (markusgraf.ch) to Hugo to enable template-based content management. The current site uses Bootstrap for styling, which will be preserved and upgraded to Bootstrap 5.x. This is a greenfield Hugo implementation with no existing templating infrastructure.
## Goals / Non-Goals
### Goals
- Create a maintainable Hugo project structure
- Preserve current website content and design
- Enable easy content updates through templates
- Establish foundation for future CV and blog sections
- Upgrade Bootstrap to latest 5.x version
### Non-Goals
- Redesigning the website appearance
- Adding new content sections (CV, blog) in this change
- Implementing JavaScript features
- Setting up automated deployment pipelines
- SEO optimization
## Decisions
### Hugo Configuration Format
**Decision**: Use `hugo.toml` (TOML format) for configuration.
**Rationale**: TOML is Hugo's default and most commonly used format, providing good readability for simple configurations.
**Alternatives considered**:
- YAML: More verbose for simple configs, but we'll keep it as an option if complex nested structures are needed later
- JSON: Less human-readable for configuration files
### Bootstrap Integration Method
**Decision**: Use CDN links for Bootstrap CSS in the base layout template.
**Rationale**:
- Simplest approach for static site
- No build process needed for CSS
- Fast loading via CDN
- Easy to upgrade versions
**Alternatives considered**:
- Local Bootstrap files: Adds unnecessary files to repository
- Hugo Pipes with SCSS: Overkill for current needs (no custom SCSS)
- npm integration: Unnecessary complexity without JavaScript build needs
### Template Organization
**Decision**: Use standard Hugo template hierarchy with baseof.html and minimal partials.
**Rationale**:
- Follows Hugo best practices
- Keeps templates DRY (Don't Repeat Yourself)
- Makes future extensions straightforward
- Header, footer, and nav are natural partial candidates
**Structure**:
```
layouts/
├── _default/
│ ├── baseof.html # Base template with Bootstrap integration
│ ├── single.html # Single page template
│ └── list.html # List template (future blog)
├── index.html # Homepage template
└── partials/
├── header.html # Site header with nav
├── footer.html # Site footer
└── nav.html # Navigation menu
```
### Content Structure
**Decision**: Start with simple markdown files in `/content` directory, one file per page.
**Rationale**:
- Simple and sufficient for current needs
- Easy to understand and maintain
- Can evolve to page bundles when needed for CV/blog
## Risks / Trade-offs
### Risk: Bootstrap CDN Availability
**Mitigation**: Use well-established CDN (jsDelivr or official Bootstrap CDN) with high uptime. Can switch to local files later if needed.
### Risk: Content Migration Accuracy
**Mitigation**: Manual review of each page after conversion. Keep reference to original HTML during development.
### Trade-off: CDN vs Local Assets
**Chosen**: CDN for simplicity and performance
**Trade-off**: Slight dependency on external service, but acceptable for personal site
## Migration Plan
### Phase 1: Setup (Tasks 1.1-1.3)
1. Run `hugo new site` to scaffold structure
2. Create and configure hugo.toml
3. Verify directory structure
### Phase 2: Templates (Tasks 2.1-3.3)
1. Build baseof.html with Bootstrap CDN links
2. Create homepage template based on current site
3. Create reusable partials
4. Test template rendering with placeholder content
### Phase 3: Content (Tasks 5.1-5.3)
1. Review and document current site structure
2. Create markdown content files
3. Copy static assets to `/static` directory
### Phase 4: Validation (Tasks 6.1-6.5)
1. Build site with `hugo`
2. Run local server with `hugo server`
3. Test all pages and responsive behavior
4. Validate HTML and accessibility
### Rollback
If Hugo migration fails or is unsatisfactory:
- Original static HTML is preserved separately
- Can revert to static hosting immediately
- No database or external dependencies to roll back
## Open Questions
None at this time. Implementation is straightforward following Hugo conventions.
@@ -0,0 +1,15 @@
## Why
The current markusgraf.ch website uses static HTML files. Converting to Hugo will provide a maintainable template-based structure that simplifies future content updates and enables easy addition of new sections (CV, blog) without duplicating code.
## What Changes
- Initialize Hugo project structure with standard directories
- Create base layout template with Bootstrap 5.x integration
- Set up reusable partials (header, footer, navigation)
- Convert existing HTML content to Hugo templates
- Configure Hugo site settings
- Add static assets from current website
## Impact
- Affected specs: hugo-site (new capability)
- Affected code: This is a greenfield implementation - no existing code affected
- Migration: Current static HTML will be referenced to recreate in Hugo templates
@@ -0,0 +1,129 @@
## ADDED Requirements
### Requirement: Hugo Project Structure
The system SHALL initialize a Hugo static site with the standard directory structure including layouts, content, static, and data directories.
#### Scenario: Hugo site initialized
- **WHEN** Hugo site is created
- **THEN** the following directories exist: layouts/, content/, static/, data/
- **AND** a hugo.toml configuration file is present at the root
#### Scenario: Hugo builds successfully
- **WHEN** running `hugo` command
- **THEN** the site builds without errors
- **AND** generates static HTML files in the public/ directory
### Requirement: Base Layout Template
The system SHALL provide a baseof.html template that defines the common HTML structure for all pages, including Bootstrap 5.x integration.
#### Scenario: Base layout includes Bootstrap
- **WHEN** any page is rendered
- **THEN** the HTML output includes Bootstrap 5.x CSS from CDN
- **AND** the page has proper HTML5 doctype and meta tags
- **AND** the page is responsive with Bootstrap's viewport meta tag
#### Scenario: Base layout includes header and footer
- **WHEN** any page is rendered
- **THEN** the page includes the header partial
- **AND** the page includes the footer partial
- **AND** the main content block is properly positioned between them
### Requirement: Reusable Partials
The system SHALL provide reusable partial templates for header, footer, and navigation components.
#### Scenario: Header partial exists
- **WHEN** baseof.html calls the header partial
- **THEN** the header is rendered with consistent styling across all pages
#### Scenario: Footer partial exists
- **WHEN** baseof.html calls the footer partial
- **THEN** the footer is rendered with consistent styling across all pages
#### Scenario: Navigation partial exists
- **WHEN** header includes navigation
- **THEN** the navigation menu renders with links to main pages
- **AND** uses Bootstrap navigation components
### Requirement: Homepage Template
The system SHALL provide an index.html template for the homepage that extends baseof.html and displays the main landing content.
#### Scenario: Homepage renders correctly
- **WHEN** accessing the root URL
- **THEN** the homepage template is used
- **AND** displays content from content/_index.md
- **AND** matches the structure of the existing markusgraf.ch homepage
### Requirement: Single Page Template
The system SHALL provide a default single.html template for individual content pages.
#### Scenario: Single page renders correctly
- **WHEN** accessing any content page
- **THEN** the single page template is used
- **AND** displays the page title
- **AND** renders the markdown content as HTML
### Requirement: Static Assets
The system SHALL serve static assets (images, fonts, CSS files) from the static/ directory.
#### Scenario: Static files are accessible
- **WHEN** a static file is placed in static/
- **THEN** it is accessible at the site root in the built site
- **AND** preserves the directory structure from static/
### Requirement: Content Management
The system SHALL support markdown files in the content/ directory that are rendered into HTML pages.
#### Scenario: Markdown content is rendered
- **WHEN** a markdown file exists in content/
- **THEN** Hugo processes it into an HTML page
- **AND** front matter variables are accessible in templates
#### Scenario: Page metadata
- **WHEN** a content file has front matter
- **THEN** title, date, and other metadata are available in templates
- **AND** can be used for page titles and navigation
### Requirement: Configuration
The system SHALL use hugo.toml for site configuration including baseURL, title, and language settings.
#### Scenario: Site configuration is applied
- **WHEN** hugo.toml contains site settings
- **THEN** those settings are used during site generation
- **AND** site title appears in page titles
- **AND** baseURL is used for absolute URLs
### Requirement: Responsive Design
The system SHALL render pages that are responsive and mobile-friendly using Bootstrap's grid system and responsive utilities.
#### Scenario: Mobile viewport
- **WHEN** viewing the site on mobile devices
- **THEN** the layout adapts to small screens
- **AND** navigation is accessible
- **AND** content is readable without horizontal scrolling
#### Scenario: Tablet and desktop viewports
- **WHEN** viewing the site on larger screens
- **THEN** the layout utilizes available space appropriately
- **AND** maintains readability and visual hierarchy
### Requirement: HTML Validity
The system SHALL generate valid HTML5 markup that passes standard validation.
#### Scenario: Valid HTML output
- **WHEN** pages are generated
- **THEN** HTML is well-formed
- **AND** includes required DOCTYPE and meta tags
- **AND** uses semantic HTML5 elements where appropriate
### Requirement: Accessibility Basics
The system SHALL implement basic accessibility features including semantic HTML and proper heading hierarchy.
#### Scenario: Semantic HTML structure
- **WHEN** pages are rendered
- **THEN** content uses appropriate semantic elements (header, nav, main, footer, article)
- **AND** maintains logical heading hierarchy (h1, h2, h3)
#### Scenario: Navigation accessibility
- **WHEN** keyboard navigation is used
- **THEN** all interactive elements are focusable
- **AND** focus order is logical
@@ -0,0 +1,31 @@
## 1. Hugo Project Setup
- [x] 1.1 Initialize Hugo site structure
- [x] 1.2 Create hugo.toml/yaml configuration file
- [x] 1.3 Set up directory structure (layouts, content, static, data)
## 2. Layout Templates
- [x] 2.1 Create baseof.html layout template
- [x] 2.2 Create index.html template for homepage
- [x] 2.3 Create default single page template
## 3. Partials
- [x] 3.1 Create header partial
- [x] 3.2 Create footer partial
- [x] 3.3 Create navigation partial
## 4. Bootstrap Integration
- [x] 4.1 Add Bootstrap 5.x CSS to project
- [x] 4.2 Configure Bootstrap in base layout
- [x] 4.3 Apply Bootstrap classes to templates
## 5. Content Migration
- [x] 5.1 Review existing markusgraf.ch HTML structure
- [x] 5.2 Create content files in Hugo format
- [x] 5.3 Migrate static assets (images, fonts, etc.)
## 6. Testing and Validation
- [x] 6.1 Test Hugo build locally
- [x] 6.2 Verify all pages render correctly
- [x] 6.3 Check responsive design on mobile/tablet/desktop
- [x] 6.4 Validate HTML output
- [x] 6.5 Test accessibility basics
@@ -0,0 +1,280 @@
# Multilingual Support Design
## Context
The site needs to support both German and English content with seamless language switching. Hugo provides built-in multilingual support that we'll leverage. The current content is in German only, stored directly in `/content/`.
## Goals / Non-Goals
### Goals
- Support German (de) and English (en) languages
- Automatic browser language detection for first-time visitors
- Persistent language preference via URL structure
- Language switcher that maintains page context (e.g., `/de/cv``/en/cv`)
- All existing content translated to English
- Clean URL structure using language codes as path prefixes
### Non-Goals
- Translation management system or CMS integration
- More than 2 languages at this stage
- Client-side JavaScript for language switching (Hugo server-side only)
- Automated translation (manual translation required)
## Decisions
### Decision 1: Hugo Multilingual Mode
**Approach**: Use Hugo's built-in multilingual mode with language code prefixes in URLs
**Rationale**:
- Hugo natively supports multilingual sites with `defaultContentLanguage` and `[languages]` config
- URL structure `/de/` and `/en/` clearly indicates language and persists preference
- No cookies or JavaScript needed for language persistence
- SEO-friendly with proper `hreflang` tags
**Alternatives Considered**:
- Subdomain approach (de.markusgraf.ch, en.markusgraf.ch): Rejected due to complexity and DNS configuration
- Client-side JavaScript switching: Rejected to keep site static and performant
### Decision 2: Content Organization
**Approach**: Reorganize content into language-specific directories `/content/de/` and `/content/en/`
**Structure**:
```
content/
├── de/
│ ├── _index.md
│ └── cv.md
└── en/
├── _index.md
└── cv.md
```
**Rationale**:
- Clear separation of language-specific content
- Hugo automatically links translations when file paths match
- Easy to maintain and scale
### Decision 3: Language Switcher Implementation
**Approach**: Add language switcher in navigation partial using Hugo's `.Translations` function
**Implementation**:
- Display language switcher as links (e.g., "DE | EN")
- Active language styled differently
- Maintains current page context when switching
- Falls back to home page if translation doesn't exist
**Rationale**:
- Simple, no JavaScript required
- Hugo provides `.Translations` to find corresponding pages
- Consistent with existing navigation patterns
### Decision 4: Default Language
**Approach**: German (de) as default with English (en) as secondary
**Configuration**:
```toml
defaultContentLanguage = "de"
defaultContentLanguageInSubdir = true
```
**Rationale**:
- Existing content is in German
- Primary audience is German-speaking
- `defaultContentLanguageInSubdir = true` ensures consistent URLs (`/de/` for German, not just `/`)
### Decision 5: Browser Language Detection
**Approach**: Hugo serves content based on URL path; Apache/Nginx handles initial redirect based on `Accept-Language` header
**Rationale**:
- Hugo is a static site generator and cannot detect browser language at runtime
- Server-side redirect is the cleanest approach
- Falls back to default language (German) if header not present
- Once user navigates, URL path maintains their choice
**Migration Path**:
1. Configure multilingual mode in hugo.toml
2. Reorganize existing content to `/content/de/`
3. Create English translations in `/content/en/`
4. Update templates with language switcher
5. Configure server redirect rules (optional, for initial visit only)
## Risks / Trade-offs
### Risk 1: Breaking Change in Content Structure
**Risk**: Moving content files breaks existing local references and workflows
**Mitigation**:
- Clear documentation of new structure
- All content moved in single commit
- Update paths in OpenSpec documentation
### Risk 2: Translation Maintenance
**Risk**: Keeping German and English content in sync over time
**Mitigation**:
- Document translation process
- Consider adding translation status tracking in future
- For now, manual process with clear ownership
### Risk 3: SEO Impact
**Risk**: URL structure changes may affect search rankings
**Mitigation**:
- Implement proper `hreflang` tags (Hugo does this automatically)
- Add redirects from old URLs to new German URLs
- Submit new sitemap to search engines
## Migration Plan
### Phase 1: Configure Hugo (No Breaking Changes Yet)
1. Update hugo.toml with multilingual configuration
2. Test configuration with existing content structure
### Phase 2: Restructure Content
1. Move existing content to `/content/de/`
2. Update any internal references
3. Build and verify German site works at `/de/`
### Phase 3: Add English Content
1. Create `/content/en/` directory
2. Translate home page content
3. Translate CV page content
4. Translate navigation and UI strings
### Phase 4: Update Templates
1. Add language switcher to navigation
2. Update partials for multilingual strings
3. Test language switching functionality
### Phase 5: Server Configuration (Optional)
1. Add .htaccess or nginx rules for browser language detection
2. Redirect root `/` to `/de/` or `/en/` based on Accept-Language header
## Open Questions
**Q: Should the root URL `/` redirect to a language version, or show a language selection page?**
A: Redirect to `/de/` as default, optionally detect browser language. No standalone language selection page needed.
**Q: How should we handle the menu configuration for different languages?**
A: Hugo supports language-specific menus using `[[languages.de.menu.main]]` and `[[languages.en.menu.main]]` in hugo.toml.
**Q: Should we translate the project descriptions on the home page?**
A: Yes, translate all visible content including project descriptions.
## Implementation Bugs and Solutions
During implementation, several critical bugs were discovered and fixed. These are documented here to avoid future pitfalls.
### Bug 1: Language Switcher Showing Current Language
**Problem**: The language switcher initially showed a dropdown with the current language as the toggle button (e.g., showing "Deutsch" when on German pages). This was confusing because users couldn't easily see which language to switch to.
**Solution**: Simplified the language switcher to only show the alternative language as a direct link. Removed the dropdown pattern and changed from:
```html
<li class="nav-item dropdown">
<a class="dropdown-toggle">{{ .Language.LanguageName }}</a>
<ul class="dropdown-menu">...</ul>
</li>
```
To:
```html
{{ if .IsTranslated }}
{{ range .Translations }}
<li class="nav-item">
<a class="nav-link" href="{{ .RelPermalink }}">{{ .Language.LanguageName }}</a>
</li>
{{ end }}
{{ end }}
```
**Lesson**: For a two-language site, showing only the alternative language is clearer than a dropdown showing the current language.
### Bug 2: Language Switcher Not Maintaining Page Context
**Problem**: When switching languages from `/de/cv/` to English, it would redirect to `/en/` (home) instead of `/en/cv/` (maintaining the CV page context).
**Solution**: Added `translationKey` to the frontmatter of both language versions of each content file to explicitly link them as translations:
```yaml
---
title: "Curriculum Vitae"
translationKey: "cv"
---
```
This allows Hugo's `.IsTranslated` and `.Translations` functions to correctly find corresponding pages.
**Lesson**: Hugo doesn't automatically recognize translations by filename alone when using language subdirectories. Always add `translationKey` to explicitly link translated pages.
### Bug 3: CV Pages Rendering with Wrong Language Context
**Problem**: The most critical bug - CV pages would render with the wrong language:
- `/en/cv/` would show `lang="de"`, German menu ("Lebenslauf"), and German language context
- Both German and English CV pages would show incorrect language switcher labels
**Root Cause**: Using language subdirectories (`content/de/cv.md` and `content/en/cv.md`) caused Hugo to incorrectly resolve the language context for these pages, even though `hugo list all` showed them with the correct language tags.
**Solution**: Reorganized content files to use Hugo's language suffix naming convention instead of subdirectories:
- Changed from: `content/de/cv.md` and `content/en/cv.md`
- Changed to: `content/cv.de.md` and `content/cv.en.md`
After this change, all pages rendered with the correct language context.
**Lesson**: With Hugo's multilingual mode and `defaultContentLanguageInSubdir = true`, use the `.{lang}.md` suffix pattern (e.g., `filename.de.md`, `filename.en.md`) rather than language subdirectories (`de/filename.md`, `en/filename.md`). The subdirectory approach can cause template rendering issues where the wrong language context is used.
### Bug 4: Home and Navbar Brand Not Respecting Language
**Problem**: Clicking the "Home" link or navbar brand from `/en/cv/` would always redirect to `/` (German home) instead of `/en/` (English home), breaking language persistence.
**Root Cause**: Both links used `{{ .Site.BaseURL }}` which always points to the absolute root URL without language awareness.
**Solution**: Changed both to use Hugo's `relLangURL` function:
```html
<!-- Before -->
<a href="{{ .Site.BaseURL }}">Home</a>
<!-- After -->
<a href="{{ "/" | relLangURL }}">Home</a>
```
This makes the links language-aware, so:
- On German pages: `{{ "/" | relLangURL }}``/de/`
- On English pages: `{{ "/" | relLangURL }}``/en/`
**Lesson**: Never use `{{ .Site.BaseURL }}` for internal navigation in multilingual sites. Always use `relLangURL` or `absLangURL` to maintain language context.
### Bug 5: Menu URLs Not Language-Aware
**Problem**: The German "Lebenslauf" menu link pointed to `/cv/` which resulted in a 404 error because with `defaultContentLanguageInSubdir = true`, German pages are at `/de/cv/`, not `/cv/`.
**Root Cause**: Menu URLs in `hugo.toml` were hardcoded:
```toml
[[languages.de.menu.main]]
url = '/cv/' # Wrong - page doesn't exist here
```
**Solution**: Updated menu URLs to include the language prefix:
```toml
[[languages.de.menu.main]]
name = 'Lebenslauf'
url = '/de/cv/' # Correct
weight = 10
[[languages.en.menu.main]]
name = 'Curriculum Vitae'
url = '/en/cv/' # Correct
weight = 10
```
**Lesson**: When `defaultContentLanguageInSubdir = true`, even the default language requires the language prefix in all URLs. Don't assume the default language is accessible at the root paths.
## Best Practices Derived from Bugs
1. **Content Organization**: Use `filename.{lang}.md` pattern instead of `{lang}/filename.md` subdirectories to avoid template context issues.
2. **Translation Linking**: Always add `translationKey` to frontmatter for explicit translation relationships.
3. **URL Generation**: Use Hugo's language-aware functions:
- `relLangURL` for relative URLs
- `absLangURL` for absolute URLs
- `.RelPermalink` for page permalinks
- Never use `{{ .Site.BaseURL }}` for internal links
4. **Menu Configuration**: When `defaultContentLanguageInSubdir = true`, all menu URLs must include the language prefix, even for the default language.
5. **Testing**: Always test all pages in all languages, not just home pages. CV/subpages may render with different template contexts than home pages.
@@ -0,0 +1,24 @@
# Add Multilingual Support (German/English)
## Why
The website is currently German-only, limiting accessibility for international visitors. Adding English language support will make the site more accessible to a global audience of HR professionals, recruiters, and potential collaborators who may not speak German.
## What Changes
- Configure Hugo's multilingual mode with German (de) as default and English (en) as secondary language
- Restructure content directory to support language-specific content (`content/de/` and `content/en/`)
- Translate all existing German content to English (home page, CV page, navigation, footer)
- Add language switcher UI component in navigation that maintains current page context
- Implement browser language detection to automatically select appropriate language for new visitors
- Preserve language preference across page navigation using URL-based language routing (`/de/` and `/en/` paths)
- Update templates to support language-specific strings and navigation
## Impact
- Affected specs: `internationalization` (new capability)
- Affected code:
- `/hugo.toml` (multilingual configuration)
- `/content/` directory structure (reorganize to language-specific subdirectories)
- `/layouts/partials/nav.html` (add language switcher)
- `/layouts/partials/header.html` (update if needed)
- All content files (duplicate and translate to English)
- User-facing: Language switcher in navigation, English version of all content, automatic language detection
- **BREAKING**: Content file paths change from `/content/*.md` to `/content/{de,en}/*.md`
@@ -0,0 +1,118 @@
# Internationalization
## ADDED Requirements
### Requirement: Multilingual Content Support
The site SHALL support multiple languages with German (de) as the default language and English (en) as a secondary language.
#### Scenario: German content is accessible at /de/ path
- **WHEN** a visitor navigates to `/de/` or any `/de/*` path
- **THEN** the page displays in German language
- **AND** all navigation, content, and UI elements are in German
#### Scenario: English content is accessible at /en/ path
- **WHEN** a visitor navigates to `/en/` or any `/en/*` path
- **THEN** the page displays in English language
- **AND** all navigation, content, and UI elements are in English
#### Scenario: All pages have translations
- **WHEN** content exists in one language
- **THEN** a corresponding translation SHALL exist in the other language
- **AND** the content structure mirrors across languages (e.g., `/de/cv``/en/cv`)
### Requirement: Language Switcher
The site navigation SHALL include a language switcher that allows users to change languages while maintaining page context.
#### Scenario: Language switcher is visible in navigation
- **WHEN** a visitor views any page
- **THEN** the navigation displays language options (DE, EN)
- **AND** the current active language is visually indicated
- **AND** the inactive language is shown as a clickable link
#### Scenario: Language switching maintains page context
- **WHEN** a visitor is on `/de/cv` and clicks the English language link
- **THEN** the page navigates to `/en/cv` (the English version of the same page)
- **AND** the page content changes to English
#### Scenario: Language switching from home page
- **WHEN** a visitor is on `/de/` and clicks the English language link
- **THEN** the page navigates to `/en/`
- **AND** the home page content changes to English
#### Scenario: Language switcher handles missing translations
- **WHEN** a visitor is on a page without a translation
- **THEN** the language link points to the home page of the target language
- **AND** the user is not left on a broken or non-existent page
### Requirement: Language Persistence
The site SHALL maintain the user's language preference through URL-based routing without requiring cookies or JavaScript.
#### Scenario: Language preference persists across navigation
- **WHEN** a visitor navigates to `/de/cv` and then clicks a navigation link
- **THEN** all subsequent pages remain in German (e.g., clicking "Home" goes to `/de/`)
- **AND** the language preference is maintained through the URL structure
#### Scenario: Direct URL access respects language
- **WHEN** a visitor directly accesses `/en/cv` via URL or bookmark
- **THEN** the page displays in English
- **AND** all navigation links point to English pages
### Requirement: Browser Language Detection
The site configuration SHALL support automatic language selection based on browser language preferences for first-time visitors.
#### Scenario: Server redirect based on Accept-Language header
- **WHEN** a visitor accesses the root URL `/` for the first time
- **THEN** the server MAY redirect to `/de/` or `/en/` based on the browser's `Accept-Language` header
- **AND** German is used as the fallback if no language preference is detected
#### Scenario: URL-based access bypasses language detection
- **WHEN** a visitor directly accesses `/de/` or `/en/`
- **THEN** the specified language is used regardless of browser settings
- **AND** no redirect occurs
### Requirement: Content Translation
All site content SHALL be translated between German and English languages.
#### Scenario: Home page content is translated
- **WHEN** viewing the home page in German (`/de/`)
- **THEN** all text including introduction, project descriptions, and UI labels are in German
- **WHEN** viewing the home page in English (`/en/`)
- **THEN** all text including introduction, project descriptions, and UI labels are in English
#### Scenario: CV page content is translated
- **WHEN** viewing the CV page in German (`/de/cv`)
- **THEN** all text including headings, instructions, and contact information are in German
- **WHEN** viewing the CV page in English (`/en/cv`)
- **THEN** all text including headings, instructions, and contact information are in English
#### Scenario: Navigation menu is translated
- **WHEN** viewing any page in German
- **THEN** navigation menu items are in German (e.g., "Lebenslauf" for CV)
- **WHEN** viewing any page in English
- **THEN** navigation menu items are in English (e.g., "Curriculum Vitae" for CV)
#### Scenario: Footer content is translated
- **WHEN** viewing any page in German
- **THEN** footer content including address and contact information labels are in German
- **WHEN** viewing any page in English
- **THEN** footer content including address and contact information labels are in English
### Requirement: SEO and Accessibility
The site SHALL implement proper multilingual SEO practices and accessibility features.
#### Scenario: HTML lang attribute is set correctly
- **WHEN** viewing a German page
- **THEN** the HTML element has `lang="de"` attribute
- **WHEN** viewing an English page
- **THEN** the HTML element has `lang="en"` attribute
#### Scenario: Alternative language links are provided
- **WHEN** viewing any page
- **THEN** the HTML head includes `<link rel="alternate" hreflang="de" ...>` and `<link rel="alternate" hreflang="en" ...>` tags
- **AND** these tags point to the corresponding page in each language
#### Scenario: Page titles reflect language
- **WHEN** viewing a page in German
- **THEN** the page title is in German
- **WHEN** viewing a page in English
- **THEN** the page title is in English
@@ -0,0 +1,70 @@
## 1. Hugo Configuration
- [x] 1.1 Update `hugo.toml` with multilingual configuration
- [x] 1.2 Set German (de) as default language with `defaultContentLanguage = "de"`
- [x] 1.3 Enable language prefix in URLs (set to false for German at root, English at /en/)
- [x] 1.4 Configure language definitions for German and English
- [x] 1.5 Set language-specific titles and metadata
- [x] 1.6 Test configuration with existing content structure
## 2. Content Structure Reorganization
- [x] 2.1 Create `/content/de/` directory
- [x] 2.2 Move existing `content/_index.md` to `content/de/_index.md`
- [x] 2.3 Move existing `content/cv.md` to `content/de/cv.md`
- [x] 2.4 Verify no content files remain in `/content/` root
- [x] 2.5 Build site and verify German content accessible at `/` and `/de/`
## 3. English Content Creation
- [x] 3.1 Create `/content/en/` directory
- [x] 3.2 Create `content/en/_index.md` with translated home page content
- [x] 3.3 Translate profile introduction and bullet points to English
- [x] 3.4 Translate project descriptions (simplified version without projects section)
- [x] 3.5 Create `content/en/cv.md` with translated CV page content
- [x] 3.6 Translate CV download instructions and notices to English
- [x] 3.7 Verify image paths work correctly from new content locations
## 4. Navigation Menu Configuration
- [x] 4.1 Update `hugo.toml` to use language-specific menu configuration
- [x] 4.2 Configure German menu with `[[languages.de.menu.main]]`
- [x] 4.3 Configure English menu with `[[languages.en.menu.main]]`
- [x] 4.4 Set menu item "Home" for both languages (handled by nav partial)
- [x] 4.5 Set menu item "Curriculum Vitae" for English and "Lebenslauf" for German
- [x] 4.6 Verify menu items display correctly in each language
## 5. Language Switcher Implementation
- [x] 5.1 Update `layouts/partials/nav.html` to add language switcher
- [x] 5.2 Display available languages (Deutsch, English) in navigation as dropdown
- [x] 5.3 Style active language in dropdown toggle
- [x] 5.4 Link language switcher to corresponding page in other language using `.Translations`
- [x] 5.5 Handle fallback to home page if translation doesn't exist
- [x] 5.6 Test language switching from home page
- [x] 5.7 Test language switching from CV page
- [x] 5.8 Verify language switcher maintains page context
## 6. Template Updates
- [x] 6.1 Review `layouts/_default/baseof.html` for language-specific updates
- [x] 6.2 Update HTML `lang` attribute to use `.Language.Lang` instead of `.Site.LanguageCode`
- [x] 6.3 Verify Hugo automatically adds `hreflang` tags (Hugo handles this automatically)
- [x] 6.4 Update footer partial (no changes needed - address is same in both languages)
- [x] 6.5 Test that page titles reflect correct language
## 7. Testing & Validation
- [x] 7.1 Test German site at `/` and `/de/` in development mode
- [x] 7.2 Test English site at `/en/` in development mode
- [x] 7.3 Verify all navigation links work in both languages
- [x] 7.4 Test language switcher from home page
- [x] 7.5 Test language switcher from CV page
- [x] 7.6 Verify active language indication in navigation dropdown
- [x] 7.7 Check that direct URL access works (e.g., `/en/cv`)
- [x] 7.8 Verify HTML lang attribute on home pages (CV pages have minor issue - noted)
- [x] 7.9 Check responsive layout in both languages (Bootstrap handles this)
- [x] 7.10 Test production build with `hugo build`
- [x] 7.11 Verify generated sitemap includes both languages
- [x] 7.12 Check hreflang tags in generated HTML (Hugo auto-generates)
## 8. Documentation
- [x] 8.1 Document new content structure in OpenSpec proposal
- [x] 8.2 Add notes about translation workflow in design.md
- [x] 8.3 Update any development guides with multilingual considerations (covered in design.md)
## Known Issues
- Minor template issue: `.Language.Lang` not resolving correctly for some CV pages in current Hugo version. Home pages work correctly. Functionality is not impacted as language switching, menus, and content all work properly.
@@ -0,0 +1,70 @@
# Design: Content Migration from markusgraf.ch
## Overview
This change migrates all existing content from the live markusgraf.ch website into the Hugo-based project structure. The migration is a one-time content extraction and conversion process.
## Approach
### Content Extraction Strategy
Since the live site cannot be automatically fetched, we rely on the user to provide:
1. HTML source code from the live site (via browser "Save As" or inspector)
2. Direct access to image URLs for downloading
### Content Conversion
- **HTML to Markdown**: Extract semantic content from HTML and convert to clean markdown
- **Preserve Structure**: Maintain the section hierarchy and flow from the live site
- **Hugo Integration**: Use Hugo's front matter and content organization patterns
### Image Handling
Images follow Hugo's static asset conventions:
- Store in `static/images/` (or appropriate subdirectory)
- Reference in markdown as `/images/filename.ext`
- Organize by purpose (e.g., `static/images/projects/`, `static/images/profile/`)
### Content Organization
```
content/
_index.md # Homepage with bio, intro, projects
about.md # About/CV page (if exists)
static/
images/
profile/ # Profile photos
projects/ # Project-related images
icons/ # Icons or small graphics (if any)
```
## Trade-offs
### Why Not Automate Extraction?
- WebFetch requires authentication (not available)
- Manual provision ensures accuracy and allows user to curate content
- One-time migration doesn't justify complex scraping infrastructure
### Content Structure Decisions
- **Single vs Multiple Pages**: If live site is single-page, we keep it as `_index.md`. If multi-page, we create separate content files
- **Project Organization**: Depending on number of projects, either:
- Inline in homepage (few projects)
- Separate section with list page (many projects)
### Image Optimization
- Accept images as-is from live site initially
- Future optimization (resizing, format conversion) can be separate change
- Prioritize content parity over optimization
## Dependencies
- Requires user to provide HTML source and ensure images are accessible
- Depends on existing Hugo site structure from `add-minimal-hugo-site` change
## Validation Strategy
- Visual comparison: Hugo build vs live site side-by-side
- Checklist verification: Every section, image, and link accounted for
- Browser console: No 404 errors or missing resources
- Accessibility: All images have alt text
## Rollback Plan
Since this is additive content migration:
- Git revert to restore placeholder content
- No breaking changes to existing Hugo structure
- Image assets can be removed from static/ directory
@@ -0,0 +1,15 @@
## Why
The Hugo site structure has been initialized but contains only placeholder content. To complete the migration from markusgraf.ch, we need to extract all actual content (text, images, and structure) from the live site and integrate it into the Hugo templates and content files. This ensures the Hugo site displays the exact same information as the current live site.
## What Changes
- Extract and migrate homepage content (bio/intro text) from markusgraf.ch
- Migrate all project/portfolio information and descriptions
- Download and organize all images from the live site into Hugo's static directory
- Update content markdown files (_index.md, etc.) with actual text content
- Ensure all internal links and image references work correctly in Hugo
- Verify visual and content parity between live site and Hugo build
## Impact
- Affected specs: content-migration (new), image-assets (new)
- Affected code: content/_index.md, content/about.md (if exists), static/ directory, potentially layout templates if content structure differs from placeholders
- Migration: One-time content extraction from live markusgraf.ch website
@@ -0,0 +1,82 @@
## ADDED Requirements
### Requirement: Content Extraction from Live Site
The system SHALL capture all text content, structure, and formatting from the live markusgraf.ch website to migrate into the Hugo project.
#### Scenario: Extract homepage content from live site
- **GIVEN** the live markusgraf.ch website HTML source is provided
- **WHEN** the HTML is parsed for content extraction
- **THEN** all text content, headings, and structure are captured
- **AND** the content is organized by logical sections (bio, intro, projects, etc.)
#### Scenario: Extract projects and portfolio content
- **GIVEN** the live site contains project or portfolio information
- **WHEN** projects are identified and extracted
- **THEN** each project has complete description captured
- **AND** project metadata and structure is documented
### Requirement: Content Conversion to Hugo Format
The system SHALL convert extracted HTML content into Hugo-compatible markdown format while preserving formatting and structure.
#### Scenario: Convert HTML to markdown
- **GIVEN** extracted HTML content from live site
- **WHEN** content is converted to markdown
- **THEN** all text formatting is preserved (bold, italic, links)
- **AND** HTML-specific elements are converted to markdown or Hugo shortcodes
- **AND** content follows markdown best practices
#### Scenario: Add Hugo front matter
- **GIVEN** converted markdown content
- **WHEN** content files are created
- **THEN** appropriate YAML front matter is added (title, description, date)
- **AND** front matter variables are correctly configured for templates
### Requirement: Homepage Content Integration
The system SHALL integrate migrated homepage content into content/_index.md, replacing placeholder content.
#### Scenario: Update homepage with actual content
- **GIVEN** converted homepage markdown content
- **WHEN** content/_index.md is updated
- **THEN** all placeholder text is replaced with actual content
- **AND** all sections from live site are present
- **AND** content hierarchy and flow matches live site structure
#### Scenario: Image references in content
- **GIVEN** homepage content references images
- **WHEN** image references are added to markdown
- **THEN** images use Hugo static path conventions (e.g., /images/photo.jpg)
- **AND** all image markdown syntax is correct
### Requirement: Content Structure Parity
The system SHALL ensure the Hugo site content structure matches the live markusgraf.ch site organization.
#### Scenario: Section organization matches live site
- **GIVEN** live site has distinct sections
- **WHEN** content is organized in Hugo
- **THEN** all sections are represented
- **AND** section order matches live site
- **AND** navigation between sections works correctly
#### Scenario: Multi-page structure if needed
- **GIVEN** live site has multiple pages
- **WHEN** pages are created in Hugo
- **THEN** each page has corresponding content file
- **AND** internal links between pages work
- **AND** navigation reflects page structure
### Requirement: Content Verification
The system SHALL verify that migrated content achieves parity with the live site.
#### Scenario: Content completeness check
- **GIVEN** Hugo site is built with migrated content
- **WHEN** compared with live markusgraf.ch
- **THEN** all text content from live site is present
- **AND** no content is missing or truncated
- **AND** content meaning and context are preserved
#### Scenario: Visual structure comparison
- **GIVEN** Hugo site is rendered
- **WHEN** viewed alongside live site
- **THEN** content sections appear in same order
- **AND** heading hierarchy matches
- **AND** overall content flow is equivalent
@@ -0,0 +1,86 @@
## ADDED Requirements
### Requirement: Image Asset Discovery
The system SHALL identify and catalog all images from the live markusgraf.ch website for migration.
#### Scenario: Identify all images on live site
- **GIVEN** the live markusgraf.ch website HTML source
- **WHEN** images are catalogued from the HTML
- **THEN** all image URLs are documented
- **AND** image purposes (profile, project, icon, etc.) are identified
- **AND** image file formats and sizes are noted
#### Scenario: Create asset inventory
- **GIVEN** identified images from live site
- **WHEN** asset inventory is created
- **THEN** a complete list of images with URLs exists
- **AND** each image is categorized by type/purpose
- **AND** inventory documents source URLs for downloading
### Requirement: Image Download and Organization
The system SHALL download images from the live site and organize them in Hugo's static directory following logical grouping principles.
#### Scenario: Download images from live site
- **GIVEN** list of image URLs from inventory
- **WHEN** images are downloaded
- **THEN** all images are successfully retrieved
- **AND** image files are verified for integrity
- **AND** no corrupted or failed downloads exist
#### Scenario: Organize images in static directory
- **GIVEN** downloaded images
- **WHEN** images are placed in Hugo project
- **THEN** images are saved to static/images/ or appropriate subdirectories
- **AND** directory structure reflects logical grouping (e.g., static/images/projects/, static/images/profile/)
- **AND** filenames are consistent and descriptive
### Requirement: Image Reference Integration
The system SHALL update all image references in content files to use Hugo's static path conventions correctly.
#### Scenario: Update image paths in content
- **GIVEN** images are in Hugo static directory
- **WHEN** content files reference images
- **THEN** image paths use Hugo static conventions (e.g., /images/photo.jpg)
- **AND** all image references use correct relative or absolute paths
- **AND** markdown image syntax is properly formatted
#### Scenario: Verify image links resolve
- **GIVEN** Hugo site is built
- **WHEN** pages with images are rendered
- **THEN** all image references resolve correctly
- **AND** no broken image links exist
- **AND** no 404 errors occur for image resources
### Requirement: Image Display Verification
The system SHALL ensure all migrated images display correctly in the built Hugo site.
#### Scenario: Images render correctly
- **GIVEN** Hugo site is built and served
- **WHEN** pages with images are viewed
- **THEN** all images display visually
- **AND** image aspect ratios are appropriate
- **AND** images load from correct static paths
- **AND** no missing or placeholder images appear
#### Scenario: Image dimensions and quality
- **GIVEN** images are displayed on site
- **WHEN** comparing to live site
- **THEN** image sizes are comparable to originals
- **AND** image quality is maintained
- **AND** no distortion or stretching occurs
### Requirement: Image Accessibility
The system SHALL ensure all images have appropriate accessibility attributes for screen readers and assistive technologies.
#### Scenario: Alt text for all images
- **GIVEN** images in content files
- **WHEN** markdown image syntax is used
- **THEN** all images include descriptive alt text
- **AND** alt text meaningfully describes image content
- **AND** decorative images use empty alt text where appropriate
#### Scenario: Semantic image usage
- **GIVEN** images serve specific purposes
- **WHEN** images are integrated into content
- **THEN** images are used semantically (figures, illustrations, etc.)
- **AND** image context is clear from surrounding content
@@ -0,0 +1,81 @@
# Tasks
## Content Extraction & Analysis
- [x] 1. **Obtain HTML source from live markusgraf.ch**
- Used curl to fetch HTML from live site
- Parsed and analyzed the structure and sections
- Identified all text content blocks (bio, projects, etc.)
- **Validation**: HTML source successfully fetched and readable
- [x] 2. **Catalog all images and assets**
- Extracted all image URLs from live site HTML
- Documented image filenames, paths, and purposes
- Created asset inventory list: 1 profile image, 3 project images
- **Validation**: Complete list of images with URLs
## Image Migration
- [x] 3. **Download all images from live site**
- Downloaded each catalogued image using curl
- Verified image integrity (file sizes confirmed)
- **Validation**: All images downloaded successfully
- [x] 4. **Organize images in static directory**
- Created subdirectories: static/images/profile/, static/images/projects/
- Placed images with consistent naming
- Documented the organization structure
- **Validation**: Images accessible via Hugo static path convention
## Content Migration
- [x] 5. **Extract and convert homepage content**
- Parsed homepage HTML to identify content sections
- Converted HTML to markdown format
- Preserved formatting (bold, italic, links, etc.)
- **Validation**: Markdown content matches original HTML structure
- [x] 6. **Update _index.md with actual content**
- Replaced placeholder content in content/_index.md
- Added proper front matter with title and description
- Integrated all homepage sections (header, services, projects)
- Updated image references to Hugo paths (/images/...)
- **Validation**: Hugo build successful
- [x] 7. **Migrate projects/portfolio content**
- Extracted all 3 project descriptions and details
- Integrated projects into homepage sections
- Added project images and linked them correctly
- **Validation**: All projects visible with complete information
- [x] 8. **Update or create additional content pages**
- Removed placeholder about.md (not present on live site)
- Live site is single-page, no additional pages needed
- **Validation**: Page structure matches live site
## Verification & Quality Assurance
- [x] 9. **Verify all internal links**
- Checked all external links (laufbahndiagnostik.ch)
- Verified email and phone links work correctly
- **Validation**: All links properly formatted in generated HTML
- [x] 10. **Verify all image references**
- Built Hugo site successfully
- Verified all images copied to public/images/
- Checked HTML output for correct image paths
- **Validation**: All images present in build output
- [x] 11. **Content parity verification**
- Compared Hugo build output with live markusgraf.ch
- Verified all text content is present (headings, lists, descriptions)
- Confirmed layout and sections match
- **Validation**: Content comparison confirms identical content
- [x] 12. **Accessibility check for images**
- Added descriptive alt text to all images
- Used semantic image descriptions in German
- **Validation**: All `<img>` tags have descriptive alt attributes
## Documentation
- [x] 13. **Document content structure**
- Content structure documented in this task file
- Image organization: static/images/profile/ and static/images/projects/
- Single-page site with all content in _index.md
- **Validation**: Task completion documented
@@ -0,0 +1,21 @@
# Change Proposal: simple-deployment
## Why
Currently there is no automated way to deploy the built Hugo site to the production server. Manual file transfers are error-prone and time-consuming. This change adds a deployment script to automate uploads via rsync over SSH, properly mirroring content (including deletions).
## What Changes
- Add deployment script `scripts/deploy.sh` that syncs `public/` directory via rsync
- Use environment variables `SSH_USER`, `SSH_HOST`, `SSH_PORT`, and `REMOTE_ROOT` for configuration
- Implement mirror behavior with `--delete` flag to remove remote files not present locally
- Implement prerequisite checks (public/ exists, rsync installed, credentials set)
- Add error handling and progress reporting
- Update documentation with deployment instructions
## Impact
- Affected specs: New `deployment` capability
- Affected code: New file `scripts/deploy.sh`
- Dependencies: Requires `rsync` to be installed
- Configuration: User must set `SSH_USER` and `SSH_HOST` environment variables
- `SSH_PORT` defaults to 22
- `REMOTE_ROOT` defaults to /httpsdocs
- No changes to existing Hugo templates, content, or build process
@@ -0,0 +1,98 @@
# Deployment Capability
## ADDED Requirements
### Requirement: Rsync Deployment Script SHALL be provided
The system SHALL provide an automated deployment script that syncs the built Hugo site to the production server via rsync over SSH, properly mirroring content.
#### Scenario: User deploys site after building
**Given** the Hugo site has been built successfully (public/ directory exists)
**And** the user has set the SSH_USER and SSH_HOST environment variables
**When** the user runs the deployment script
**Then** the script connects to the specified SSH_HOST via rsync over SSH
**And** syncs all files from the public/ directory to the REMOTE_ROOT directory on the server
**And** deletes remote files that don't exist locally (mirror behavior)
**And** displays sync progress and completion status
**And** exits with status code 0 on success
#### Scenario: Script fails when credentials are missing
**Given** the Hugo site has been built
**And** the SSH_USER or SSH_HOST environment variable is not set
**When** the user runs the deployment script
**Then** the script displays an error message explaining the missing configuration
**And** exits with a non-zero status code
**And** does not attempt to connect to the server
#### Scenario: Script handles connection failures gracefully
**Given** the SSH_USER and SSH_HOST are set correctly
**And** the network connection to the server is unavailable or SSH authentication fails
**When** the user runs the deployment script
**Then** the script displays a clear error message about the connection failure
**And** exits with a non-zero status code
**And** does not leave the deployment in a partially completed state
### Requirement: Secure Credential Management SHALL be enforced
The deployment process SHALL handle credentials securely without exposing them in version control or script output.
#### Scenario: Configuration stored as environment variables
**Given** the user needs to deploy the site
**When** the user reviews the deployment documentation
**Then** the documentation instructs them to set SSH_USER, SSH_HOST, SSH_PORT, and REMOTE_ROOT as environment variables
**And** the deployment script reads configuration only from environment variables
**And** credentials are never hardcoded in scripts or configuration files
**And** SSH key-based authentication is used for secure, password-less access
#### Scenario: Script does not expose credentials in output
**Given** the deployment script is running
**When** the script displays status messages or logs
**Then** SSH keys or passwords are never displayed in plain text
**And** connection strings show only the host and user information
**And** error messages do not reveal credential values
### Requirement: Deployment Status Feedback SHALL be provided
The deployment script SHALL provide clear feedback about the deployment process and outcome.
#### Scenario: User receives progress updates during deployment
**Given** the deployment script is uploading files
**When** the upload is in progress
**Then** the script displays which files or directories are being uploaded
**And** shows overall progress indicators
**And** provides estimated time or completion percentage when possible
#### Scenario: Successful deployment confirmation
**Given** all files have been uploaded successfully
**When** the deployment completes
**Then** the script displays a success message
**And** confirms the total number of files uploaded
**And** exits with status code 0
#### Scenario: Failed deployment with actionable error
**Given** an error occurs during deployment
**When** the deployment fails
**Then** the script displays the specific error encountered
**And** suggests possible remediation steps
**And** exits with a non-zero status code
### Requirement: Deployment Prerequisites SHALL be verified
The deployment script SHALL verify that prerequisites are met before attempting deployment.
#### Scenario: Script checks for built site
**Given** the user runs the deployment script
**When** the script starts
**Then** it verifies that the public/ directory exists
**And** contains files to deploy
**And** exits with an error if the directory is missing or empty
#### Scenario: Script checks for required tools
**Given** the deployment script starts
**When** it performs prerequisite checks
**Then** it verifies that rsync is installed and available
**And** displays an installation message if rsync is missing
**And** exits with an error if required tools are unavailable
#### Scenario: Script supports configurable ports and remote directories
**Given** the user needs to deploy to a non-standard SSH port or directory
**When** the user sets SSH_PORT and REMOTE_ROOT environment variables
**Then** the script uses the specified port instead of the default (22)
**And** the script uploads to the specified remote directory instead of the default (/httpsdocs)
**And** if these variables are not set, the script uses sensible defaults
@@ -0,0 +1,88 @@
# Tasks: simple-deployment
## Implementation Tasks
### 1. Create deployment script structure
- [x] Create `scripts/` directory in project root if it doesn't exist
- [x] Create `scripts/deploy.sh` with proper shebang and execution permissions
- [x] Add basic script structure with functions for connection, upload, and error handling
- **Validates**: Script file exists and is executable
### 2. Implement prerequisite checks
- [x] Check for existence and non-empty state of `public/` directory
- [x] Verify `rsync` is installed and available in PATH
- [x] Check that `SSH_USER` and `SSH_HOST` environment variables are set
- [x] Display clear error messages for any missing prerequisites
- **Validates**: Script exits early with helpful errors when prerequisites are missing
### 3. Implement SSH/rsync connection logic
- [x] Configure rsync to connect using SSH_USER and SSH_HOST
- [x] Support configurable SSH_PORT (defaults to 22)
- [x] Support configurable REMOTE_ROOT (defaults to /httpsdocs)
- [x] Use SSH key-based authentication for secure, password-less access
- **Validates**: Script can establish SSH connection with correct credentials
### 4. Implement file sync functionality
- [x] Use rsync command to sync `public/` contents to remote directory
- [x] Configure sync to preserve file permissions and timestamps (-a flag)
- [x] Enable compression during transfer (-z flag)
- [x] Implement mirror behavior with --delete flag (removes remote files not present locally)
- [x] Handle all file types appropriately
- **Validates**: All files from public/ are correctly synced to the remote directory and old files are removed
### 5. Add progress and status reporting
- [x] Display connection status messages
- [x] Show sync progress through rsync verbose output
- [x] Report sync completion with summary
- [x] Ensure SSH keys or passwords are never displayed in output
- **Validates**: User receives clear feedback during deployment process
### 6. Implement error handling
- [x] Catch connection failures with descriptive error messages
- [x] Handle partial upload failures gracefully
- [x] Provide actionable error messages for common failure scenarios
- [x] Set appropriate exit codes (0 for success, non-zero for failures)
- **Validates**: Script handles errors gracefully and provides useful feedback
### 7. Add script documentation
- [x] Add header comments explaining script purpose and usage
- [x] Document required environment variables (SSH_USER, SSH_HOST, SSH_PORT, REMOTE_ROOT)
- [x] Include example usage in comments
- [x] Add inline comments for rsync command options
- **Validates**: Script is self-documenting for future maintenance
### 8. Update project documentation
- [x] Add deployment section to README.md or create DEPLOYMENT.md
- [x] Document environment variable setup process
- [x] Provide example deployment workflow (build → deploy)
- [x] Include troubleshooting tips for common issues
- **Validates**: User documentation exists and covers deployment process
### 9. Test deployment script
- [x] Test with missing prerequisites (no public/, no rsync, no SSH_USER/SSH_HOST)
- [x] Test with SSH authentication issues
- [x] Test successful deployment with valid credentials and SSH keys
- [x] Verify synced files match local public/ directory
- [x] Verify remote files are deleted when removed locally (mirror behavior)
- **Validates**: Script behaves correctly in success and failure scenarios
### 10. Create .gitignore entry for environment files
- [x] Ensure .env files are ignored if user creates them locally
- [x] Verify credentials cannot be accidentally committed
- **Validates**: Git ignores any credential-containing files
## Dependency Notes
- Tasks 1-2 must complete before task 3
- Tasks 3-4 must complete before task 5
- Task 6 can be implemented in parallel with tasks 3-5
- Tasks 7-8 can be done after core implementation (tasks 1-6)
- Task 9 requires all implementation tasks (1-6) to be complete
- Task 10 can be done at any time
## Testing Strategy
Manual testing is sufficient for this change:
1. Test prerequisite checks by intentionally removing prerequisites
2. Test with invalid credentials to verify error handling
3. Test successful deployment to production server
4. Verify all files are present and correct on server after deployment
5. Test script output for clarity and absence of credential exposure