30 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
KGPZ Web is a Go-based web application for serving historical newspaper data from the KGPZ (Königsberger Gelehrte und Politische Zeitung) digital archive. The application combines server-rendered HTML with HTMX for progressive enhancement, providing a modern web interface for browsing historical content.
Architecture
The application follows a modular Go architecture:
- Main Application:
kgpz_web.go- Entry point and application lifecycle management - App Core:
app/kgpz.go- Core business logic and data processing - Controllers: Route handlers for different content types (issues, agents, places, categories, search, quickfilters)
- View Models: Data structures for template rendering with pre-processed business logic (
viewmodels/) - XML Models: Data structures for parsing source XML files (
xmlmodels/) - Providers: External service integrations (Git, GND, XML parsing, search)
- Templating: Custom template engine with Go template integration and helper functions
- Views: Frontend assets and templates in
views/directory
Key Components
- Data Sources: XML files from Git repository containing historical newspaper metadata
- Search: Full-text search powered by Bleve search engine
- External Integrations: GND (Gemeinsame Normdatei) for person metadata, Geonames for place data
- Template System: Custom engine supporting layouts and partials with embedded filesystem and helper functions
Development Commands
Go Backend
# Run the application in development mode
go run kgpz_web.go
# Build the application
go build -o kgpz_web kgpz_web.go
# Run tests
go test ./helpers/xsdtime/
# Format code
go fmt ./...
# Check for issues
go vet ./...
Note: The project maintainer handles all Go compilation, testing, and error reporting. Claude Code should not run Go build commands or tests - any Go-related errors will be reported directly by the maintainer.
Frontend Assets (from views/ directory)
cd views/
# Development server with hot reloading
npm run dev
# Build production assets
npm run build
# Build CSS with Tailwind
npm run tailwind
# Build CSS with PostCSS
npm run css
# Preview built assets
npm run preview
Configuration
The application uses JSON configuration files:
config.dev.json- Development configuration (if exists)config.json- Default configuration (fallback)
Key configuration options:
git_url: Source repository URL for datagit_branch: Branch to use for datawebhook_endpoint: GitHub webhook endpoint for auto-updatesdebug: Enable debug mode and loggingwatch: Enable file watching for template hot-reloading
Data Flow
- Startup: Application clones/pulls Git repository with XML data
- Parsing: XML files parsed into structured models (agents, places, works, issues)
- Enrichment: External APIs (GND, Geonames) enrich metadata
- Indexing: Full-text search index built using Bleve
- Serving: HTTP server serves templated content with HTMX interactions
Key Dependencies
- Web Framework: Fiber (high-performance HTTP framework)
- Search: Bleve (full-text search engine)
- Git Operations: go-git (Git repository operations)
- Frontend: HTMX + Tailwind CSS for progressive enhancement
- Build Tools: Vite for asset bundling, PostCSS for CSS processing
Template Structure
Templates are embedded in the binary:
- Layouts:
views/layouts/- Base page structures - Routes:
views/routes/- Page-specific templates - Assets:
views/assets/- Compiled CSS and static files
The template system supports nested layouts and automatic reloading in development mode when watch: true is enabled.
Views Directory Structure
The views/ directory contains all frontend templates, assets, and build configuration:
Directory Layout
views/
├── layouts/ # Base templates and layouts
│ ├── components/ # Shared layout components (_header, _footer, _menu)
│ └── default/ # Default layout (root.gohtml)
├── routes/ # Page-specific templates
│ ├── akteure/ # Agents/People pages (body.gohtml, head.gohtml)
│ ├── autoren/ # Authors-only pages (body.gohtml, head.gohtml)
│ ├── ausgabe/ # Issue pages with components
│ │ └── components/ # Issue-specific components (_inhaltsverzeichnis, _bilder, etc.)
│ ├── components/ # Shared route components
│ │ ├── _akteur.gohtml # Main agent component (uses sub-components)
│ │ ├── _akteur_header.gohtml # Agent name, dates, professions, links
│ │ ├── _akteur_werke.gohtml # Works section with categorized pieces
│ │ ├── _akteur_beitraege.gohtml # Contributions/pieces with grouping
│ │ └── _piece_summary.gohtml # Individual piece display logic
│ ├── datenschutz/ # Privacy policy
│ ├── edition/ # Edition pages
│ ├── filter/ # Quickfilter system
│ ├── kategorie/ # Category pages
│ ├── kontakt/ # Contact pages
│ ├── ort/ # Places pages
│ ├── piece/ # Multi-issue piece pages
│ │ └── components/ # Piece-specific components (_piece_inhaltsverzeichnis, _piece_sequential_layout)
│ ├── search/ # Search pages
│ └── zitation/ # Citation pages
├── assets/ # Compiled output assets
│ ├── css/ # Compiled CSS files
│ ├── js/ # JavaScript libraries and compiled scripts
│ ├── fonts/ # Font files
│ ├── logo/ # Logo and favicon files
│ └── xslt/ # XSLT transformation files
├── public/ # Static public assets
├── transform/ # Source files for build process
│ ├── main.js # Main JavaScript entry point
│ └── site.css # Source CSS with Tailwind directives
└── node_modules/ # NPM dependencies
Template System
Layout Templates (layouts/):
default/root.gohtml: Base HTML structure with head, HTMX, Alpine.js setupcomponents/_header.gohtml: Site header with navigationcomponents/_footer.gohtml: Site footercomponents/_menu.gohtml: Main navigation menu
Route Templates (routes/):
Each route has dedicated head.gohtml and body.gohtml files following Go template conventions:
- Pages use German naming:
akteure(agents),ausgabe(issues),ort(places), etc. - Component partials prefixed with
_(e.g.,_akteur.gohtml,_inhaltsverzeichnis.gohtml) - HTMX-powered interactions for dynamic content loading
Template Features:
- Go template syntax with custom functions from
templating/engine.go - Block template inheritance system
- HTMX integration for progressive enhancement
- Conditional development/production asset loading
- Template helper functions for UI components (PageIcon, BeilagePageIcon)
- Pre-processed view models to minimize template logic
Frontend Assets
JavaScript Stack:
- HTMX: Core interactivity and AJAX requests
- Alpine.js: Lightweight reactivity for UI components
- Modular Architecture: ES6 modules with focused responsibilities
- Web Components: Custom elements for self-contained functionality
- Build Tool: Vite for module bundling and development server
CSS Stack:
- Tailwind CSS v4: Utility-first CSS framework
- PostCSS: CSS processing pipeline
- RemixIcon: Icon font library
- Custom Fonts: Typography setup in
assets/css/fonts.css
JavaScript Module Structure:
main.js: Entry point, HTMX event handling, citation link management, page backdrop stylingakteure.js: AkteureScrollspy web component for agents/authors navigationissue.js: Newspaper layout, page navigation, modal functions, citation generationsingle-page-viewer.js: SinglePageViewer web component for image modal displayscroll-to-top.js: ScrollToTopButton web component for floating scroll button
Build Process:
- Source:
transform/main.jsandtransform/site.css - Output: Compiled to
assets/scripts.jsandassets/style.css - Vite Config: Production build targeting ES modules
- PostCSS Config: Tailwind CSS processing
Asset Loading Strategy
The root template conditionally loads assets based on environment:
- Development: Uses dev favicon, enables hot reloading
- Production: Optimized assets, production favicon
- Module imports: ES6 modules with
setup()function from compiled scripts - Deferred loading: HTMX and Alpine.js loaded with
deferattribute
Template Architecture & Best Practices
View Model Philosophy
The application follows a logic-in-Go, presentation-in-templates approach:
- View Models (
viewmodels/issue_view.go): Pre-process all business logic, calculations, and data transformations - Templates: Focus purely on presentation using pre-calculated data
- Helper Functions (
templating/engine.go): Reusable UI components and formatting
Key View Model Features
- Pre-calculated metadata: Page icons, grid layouts, visibility flags
- Grouped data structures: Complex relationships resolved in Go
- Template helpers:
PageIcon(),BeilagePageIcon()for consistent UI components
Template Organization
Ausgabe (Issue) Templates:
body.gohtml: Main layout structure with conditional renderingcomponents/_inhaltsverzeichnis.gohtml: Table of contents with pre-processed page datacomponents/_newspaper_layout.gohtml: Newspaper page grid with absolute positioningcomponents/_bilder.gohtml: Simple image gallery fallback- Interactive highlighting system with intersection observer and scroll detection
JavaScript Integration
- Progressive Enhancement: HTMX + Alpine.js for interactivity
- Real-time Highlighting: Intersection Observer API with scroll fallback (issue view)
- Scrollspy Navigation: Multi-item highlighting system for agents/authors pages
- Page Navigation: Smooth scrolling with visibility detection
- HTMX Integration: Automatic cleanup and re-initialization on page swaps
- Responsive Design: Mobile-optimized with proper touch interactions
Development Workflow
- Backend changes: Modify Go files, restart server
- Template changes: Edit templates in
views/, automatic reload if watching enabled - CSS changes: Run
npm run cssornpm run tailwindin views directory - JavaScript changes: Edit
transform/main.js, runnpm run build - Full rebuild:
go buildfor backend,npm run buildfor frontend assets
Adding New Template Logic
- First: Add business logic to view models in Go
- Second: Create reusable template helper functions if needed
- Last: Use pre-processed data in templates for presentation only
Multi-Issue Piece View (/beitrag/)
The application supports viewing pieces/articles that span multiple issues through a dedicated piece view interface that aggregates content chronologically.
URL Structure & Routing
URL Pattern: /beitrag/:id where ID is the piece's XML ID
- Example:
/beitrag/piece-abc123(piece with XML ID "piece-abc123") - Route Definition:
PIECE_URL = "/beitrag/:id"inapp/kgpz.go - Controller:
controllers.GetPiece(k.Library)handles piece lookup and rendering
Architecture & Components
Controller (controllers/piece_controller.go):
- Looks up pieces directly by XML ID
- Handles piece aggregation across multiple issues
- Returns 404 for invalid IDs or non-existent pieces
View Model (viewmodels/piece_view.go):
PieceVMstruct aggregates data from multiple issuesAllIssueRefs []xmlmodels.IssueRef- chronologically ordered issue referencesAllPages []PiecePageEntry- sequential page data with image paths- Pre-processes page icons, grid layouts, and visibility flags
- Resolves image paths using registry system
Template System (views/routes/piece/):
body.gohtml- Two-column layout with Inhaltsverzeichnis and sequential pageshead.gohtml- Page metadata and title generationcomponents/_piece_inhaltsverzeichnis.gohtml- Table of contents with piece contentcomponents/_piece_sequential_layout.gohtml- Chronological page display
Key Features
Multi-Issue Aggregation:
- Pieces spanning multiple issues are unified in a single view
- Chronological ordering preserves reading sequence across issue boundaries
- Issue context (year/number) displayed with each page for reference
Component Reuse:
- Reuses
_inhaltsverzeichnis_eintragtemplate for consistent content display - Integrates with existing
_newspaper_layoutcomponents for single-page viewer - Shares highlighting system and navigation patterns with issue view
Sequential Layout:
- Two-column responsive design: Inhaltsverzeichnis (1/3) + Page Layout (2/3)
- Left-aligned page indicators with format:
[icon] YYYY Nr. XX, PageNum - No grid constraints - simple sequential flow for multi-issue reading
Highlighting System Integration:
- Uses same intersection observer system as issue view (
main.js) - Page links in Inhaltsverzeichnis turn red when corresponding page is visible
- Page indicators above images also highlight during scroll
- Automatic scroll-to-highlighted functionality
Template Integration
Helper Functions (templating/engine.go):
GetPieceURL(year, issueNum, page int) string- generates piece URLs- Reuses existing
PageIcon()for consistent icon display getImagePathFromRegistry()for proper image path resolution
Data Attributes for JavaScript:
data-page-containeron page containers for scroll detectiondata-page-numberon Inhaltsverzeichnis links for highlightingnewspaper-page-containerclass for intersection observerinhalts-entryclass for hover and highlighting behavior
Responsive Behavior:
- Mobile: Single column with collapsible Inhaltsverzeichnis
- Desktop: Fixed two-column layout with sticky table of contents
- Single-page viewer integration with proper navigation buttons
Usage Examples
Linking to Pieces:
<a href="{{ GetPieceURL $piece.ID }}">
gesamten beitrag anzeigen
</a>
Page Navigation in Inhaltsverzeichnis:
<a href="/{{ $pageEntry.IssueYear }}/{{ $pageEntry.IssueNumber }}/{{ $pageEntry.PageNumber }}"
class="page-number-inhalts" data-page-number="{{ $pageEntry.PageNumber }}">
{{ $issueRef.When.Day }}.{{ $issueRef.When.Month }}.{{ $issueRef.When.Year }} [Nr. {{ $pageEntry.IssueNumber }}], {{ $pageEntry.PageNumber }}
</a>
Error Handling
Invalid IDs: Returns 404 for non-existent piece IDs Missing Pieces: Returns 404 when piece lookup fails in XML data Missing Images: Graceful fallback with "Keine Bilder verfügbar" message Cross-Issue Navigation: Handles pieces spanning non-consecutive issues
Direct Page Navigation System
The application provides a direct page navigation system that allows users to jump directly to any page by specifying year and page number, regardless of which issue contains that page.
URL Structure
New URL Format: All page links now use path parameters instead of hash fragments:
- Before:
/1771/42#page-166 - After:
/1771/42/166
This change applies to all page links throughout the application, including:
- Page sharing/citation links
- Inhaltsverzeichnis page navigation
- Single page viewer navigation
Page Jump Interface
Location: Available on year overview pages (/jahrgang/:year)
Features:
- Year Selection: Dropdown with all available years (1764-1779)
- Page Input: Numeric input with validation
- HTMX Integration: Real-time error feedback without page reload
- Auto-redirect: Successful lookups redirect to
/year/issue/page
URL Patterns:
- Form Submission:
POST /jumpwith form data - Direct URL:
GET /jump/:year/:page(redirects to found issue)
Error Handling
Comprehensive Validation:
- Invalid Year: Years outside 1764-1779 range
- Invalid Page: Non-numeric or negative page numbers
- Page Not Found: Page doesn't exist in any issue of specified year
- Form Preservation: Error responses maintain user input for correction
HTMX Error Responses:
- Form replaced with error version showing red borders and error messages
- Specific error targeting (year field vs. page field)
- Graceful degradation with clear user feedback
Auto-Scroll Implementation
URL-Based Navigation:
- Pages accessed via
/year/issue/pageauto-scroll to target page - JavaScript detects path-based page numbers (not hash fragments)
- Smooth scrolling with proper timing for layout initialization
- Automatic highlighting in Inhaltsverzeichnis
Technical Implementation:
// Auto-scroll on page load if targetPage is specified
const pathParts = window.location.pathname.split('/');
if (pathParts.length >= 4 && !isNaN(pathParts[pathParts.length - 1])) {
const pageNumber = pathParts[pathParts.length - 1];
// Scroll to page container and highlight
}
Controller Architecture
Page Jump Controller (controllers/page_jump_controller.go):
FindIssueByYearAndPage()- Lookup function for issue containing specific pageGetPageJump()- Handles direct URL navigation (/jump/:year/:page)GetPageJumpForm()- Handles form submissions (POST /jump)- Error rendering with HTML form generation
Issue Controller Updates (controllers/ausgabe_controller.go):
- Enhanced to handle optional page parameter in
/:year/:issue/:page? - Page validation against issue page ranges
- Target page passed to template for auto-scroll JavaScript
Link Generation Updates
JavaScript Functions (views/transform/main.js):
copyPagePermalink()- Generates/year/issue/pageURLsgeneratePageCitation()- Uses new URL format for citationsscrollToPageFromURL()- URL-based navigation (replaces hash-based)
Template Integration:
- Page links updated throughout templates to use new URL format
- Maintains backward compatibility for beilage/supplement pages (still uses hash)
- HTMX navigation preserved with new URL structure
Usage Examples
Direct Page Access:
http://127.0.0.1:8080/1771/42/166 # Direct link to page 166
Page Jump Form:
<form hx-post="/jump" hx-swap="outerHTML">
<select name="year">...</select>
<input type="number" name="page" />
<button type="submit">Zur Seite springen</button>
</form>
Link Generation:
// New format for regular pages
const pageUrl = `/${year}/${issue}/${pageNumber}`;
// Old format still used for beilage pages
const beilageUrl = `${window.location.pathname}#beilage-1-page-${pageNumber}`;
Quickfilter System (/filter)
The application provides a universal quickfilter system accessible from any page via a header button, offering quick access to common navigation and filtering tools.
Architecture & Integration
Header Integration (views/layouts/components/_header.gohtml & _menu.gohtml):
- Universal Access: Schnellfilter button available in every page header
- Expandable Design: Header expands downwards to show filter content
- HTMX-Powered: Dynamic loading of filter content without page refresh
- Seamless UI: Integrates with existing header styling and layout
Controller (controllers/filter_controller.go):
GetQuickFilter(kgpz *xmlmodels.Library)- Renders filter interface- Uses "clear" layout for partial HTML fragments
- Dynamically extracts available years from issue data
Template System (views/routes/filter/body.gohtml):
- Clean, responsive filter interface with modern styling
- Expandable structure for future filter options
- Integrates existing functionality (page jump) in unified interface
Current Features
Page Jump Integration:
- Moved from year pages: "Direkt zu Seite springen" functionality relocated from
/jahrgang/pages to header - Universal availability: Now accessible from any page in the application
- Same functionality: Year dropdown, page input, error handling, HTMX validation
- Consistent UX: Maintains all existing behavior and error feedback
UI Components:
- Toggle Button: Filter icon in header with hover effects and visual feedback
- Expandable Container: Header expands naturally to accommodate filter content
- Responsive Design: Mobile-friendly with proper touch interactions
- Click-Outside Close: Filter closes when clicking outside the container
Technical Implementation
URL Structure:
- Filter Endpoint:
GET /filter- Renders filter interface using clear layout - Route Configuration:
FILTER_URL = "/filter"defined inapp/kgpz.go
JavaScript Functionality (views/layouts/components/_menu.gohtml):
// Toggle filter visibility
function toggleFilter() {
const filterContainer = document.getElementById('filter-container');
const filterButton = document.getElementById('filter-toggle');
if (filterContainer.classList.contains('hidden')) {
filterContainer.classList.remove('hidden');
filterButton.classList.add('bg-slate-200');
} else {
filterContainer.classList.add('hidden');
filterButton.classList.remove('bg-slate-200');
}
}
// Close filter when clicking outside
document.addEventListener('click', function(event) {
// Automatic close functionality
});
HTMX Integration:
<button id="filter-toggle"
hx-get="/filter"
hx-target="#filter-container > div"
hx-swap="innerHTML"
onclick="toggleFilter()">
<i class="ri-filter-2-line"></i> Schnellfilter
</button>
Layout System
Header Expansion:
- Natural Flow: Filter container expands header downwards using normal document flow
- Content Displacement: Page content moves down automatically when filter is open
- Visual Consistency: Uses same
bg-slate-50background as header - Centered Content: Filter content centered within expanded header area
Template Structure:
<!-- Header container expands naturally -->
<div id="filter-container" class="mt-6 hidden">
<div class="flex justify-center">
<!-- Filter content loaded here via HTMX -->
</div>
</div>
Extensible Design
Future Enhancement Ready:
- Modular template structure allows easy addition of new filter options
- Controller can be extended to handle additional filter types
- Template includes placeholder section for "Weitere Filter"
- Architecture supports complex filtering without performance impact
Data Processing:
- Efficient year extraction from issue data using same pattern as
year_view.go - Sorted year list generation with proper deduplication
- Ready for additional data aggregation (categories, agents, places)
Usage Examples
Template Integration:
<!-- Filter automatically available in all pages via header -->
<!-- No additional template includes needed -->
Controller Extension:
// Example of extending filter data
data := fiber.Map{
"AvailableYears": availableYears,
"Categories": categories, // Future enhancement
"TopAgents": topAgents, // Future enhancement
}
Migration Impact
Improved User Experience:
- Reduced Page Clutter: Removed page jump form from year overview pages
- Universal Access: Page jumping now available from anywhere in the application
- Cleaner Year Pages:
/jahrgang/pages now focus purely on year navigation - Consistent Interface: Single location for all quick navigation tools
Agents/Authors View System (/akteure/ and /autoren/)
The application provides sophisticated person and organization browsing through dual view systems with advanced navigation and filtering capabilities.
Dual View Architecture
General Agents View (/akteure/):
- Displays all persons and organizations mentioned in the newspaper
- Supports letter-based navigation (A-Z)
- Individual person pages with detailed information
- Two-column layout with scrollspy navigation on large screens
Authors-Only View (/autoren/):
- Filtered view showing only people who authored pieces (Beiträge)
- Single-page display of all authors regardless of starting letter
- No alphabet navigation (all authors shown together)
- Same advanced layout and scrollspy functionality
URL Structure & Navigation
URL Patterns:
/akteure/- All persons overview/akteure/a- Persons starting with letter "A"/akteure/{id}- Individual person page/akteure/autoren- Authors-only filtered view
Toggle Navigation:
- Checkbox interface: "Nur Autoren anzeigen" switches between views
- HTMX-powered transitions with URL history management
- Unchecking returns to
/akteure/a(letter A starting point)
Template Architecture & Components
Modular Template System (views/routes/components/):
_akteur.gohtml- Main component using sub-components_akteur_header.gohtml- Name, life dates, professions, external links_akteur_werke.gohtml- Works section with categorized pieces_akteur_beitraege.gohtml- Contributions/pieces with grouping
Component Benefits:
- Reusable across different view contexts
- Maintainable separation of concerns
- Consistent styling and behavior
- Easy customization for specific views (authors vs. full agents)
Advanced Scrollspy Navigation
Full-Height Sidebar (2XL+ screens only):
- Fixed 320px width with full viewport height
- Sticky positioning that follows scroll
- Complete name list with smooth scrolling navigation
- Automatic cleanup on HTMX page transitions
Multi-Item Highlighting:
- Highlights ALL currently visible authors simultaneously
- Red left border indicating visible items (matches issue view pattern)
- Header visibility detection (name, life data, professions must be fully visible)
- Real-time updates during scroll with 50ms debouncing
Visual Features:
- Larger text (
text-base) for better readability - Closer spacing (
py-1) for more names visible - Smooth transitions and hover effects
- Blue background highlighting for active items
Controller Architecture
Unified Controller (controllers/akteur_controller.go):
- Handles both general agents and authors-only views
- Special routing for "autoren" parameter
- Template path switching based on view type
- Letter-based filtering and ID lookup
View Models (viewmodels/agent_view.go):
AgentsView()- General person lookup by letter/IDAuthorsView()- Filtered view of piece authors onlyAuthorsListViewstruct with sorting and letter availability- Pre-processed agent data for efficient template rendering
Template Features & Data Processing
Enhanced Data Presentation:
- Grouped pieces by title and work reference
- Category combination with proper German grammar ("und" vs. "mit")
- Inline citation format: DD.MM.YYYY/ISSUENO, PPP[-PPP]
- Works section showing review/commentary pieces
- External link integration (Wikipedia, GND, VIAF)
Text Sizing & Hierarchy:
- Large serif names (
text-2xl font-serif font-bold) - Readable life dates and professions (
text-xl) - Appropriately sized content text (
text-lg) - Larger pill text (
text-sm) matching issue view standards
JavaScript Integration
HTMX-Safe Scrollspy (views/transform/main.js):
- Proper event listener cleanup on page navigation
- Memory leak prevention with timeout management
- Auto-initialization detection for
.author-sectionelements - Smooth scroll behavior for sidebar navigation
Performance Optimizations:
- Debounced scroll handling (50ms)
- Efficient viewport calculations using
getBoundingClientRect() - Minimal DOM queries with cached element references
- Responsive behavior with automatic sidebar hiding
Responsive Design
Desktop Experience (2XL+ screens):
- Two-column layout: 320px sidebar + flexible content area
- Fixed scrollspy navigation with full name list
- Multi-author highlighting system
- Smooth scrolling between authors
Mobile Experience (< 2XL screens):
- Single-column layout with full-width content
- Hidden scrollspy navigation (saves space)
- Touch-optimized interactions
- Same content organization and functionality
Data Categories & Processing
Comprehensive Category Support:
- All 29 XML-defined categories supported
- Dynamic category detection and grouping
- Proper German grammar rules for combinations
- Author filtering for non-current-user pieces
Helper Functions (templating/engine.go):
merge,append,slice- Data manipulationsortStrings,unique- Array processingjoinWithUnd- German grammar formatting- Enhanced data processing for complex template logic
Usage Examples
Template Integration:
{{ template "_akteur_header" $agent }}
{{ template "_akteur_werke" $agent }}
{{ template "_akteur_beitraege" $agent }}
Scrollspy Navigation:
<a href="#author-{{ $id }}"
class="scrollspy-link border-l-4 border-transparent"
data-target="author-{{ $id }}">
{{ index $agent.Names 0 }}
</a>
HTMX Toggle:
<input type="checkbox"
hx-get="/akteure/autoren"
hx-target="body"
hx-push-url="true">
Error Handling & Edge Cases
Template Safety:
- Null checks for GND data and agent information
- Graceful fallback for missing names or professions
- Safe handling of empty work/piece lists
- Error boundaries for external link data
Navigation Robustness:
- 404 handling for invalid agent IDs
- Automatic fallback for missing letters
- Smooth transitions between view modes
- Proper state management across HTMX swaps