'https://wp.dejvino.com/', 'Projects' => 'https://projects.dejvino.com/', 'Code' => 'https://git.dejvino.cz/', ]; $highlights = $cvData['highlights'] ?? []; /** * Sourced Interests Showcase (from data.json) */ $interests_showcase = []; if (!empty($cvData['interests'])) { foreach ($cvData['interests'] as $item) { $img = $item['image'] ?? null; $has_image = $img && file_exists(__DIR__ . '/' . $img); $interests_showcase[] = [ 'name' => $item['name'] ?? '', 'image' => $has_image ? $img : null, 'caption' => $item['caption'] ?? '' ]; } } $site_url = "https://www.dejvino.cz/"; $site_title = $name; $site_desc = "$name - $headline"; $extra_contact_links = $cvData['contact_links'] ?? []; /** * Emoji icons for link pills */ $pill_icons = [ 'Website' => '🌐', 'Email' => '✉️', 'Resume' => '📄', 'CV' => '📄', 'PDF' => '📑', 'Blog' => '✍️', 'Projects' => '📁', 'Code' => '💻', 'GitLab' => '🔶', 'GitHub' => '🐙', ]; /** MACHINE READABLE ENDPOINTS */ $parsedUrl = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); if (in_array($parsedUrl, ['/api/data.json', '/api/data.json/'], true)) { header('Content-Type: application/json; charset=utf-8'); header('Access-Control-Allow-Origin: *'); readfile(__DIR__ . '/data.json'); exit; } if (in_array($parsedUrl, ['/llms.txt', '/llms.txt/'], true)) { header('Content-Type: text/plain; charset=utf-8'); echo '# ' . $site_url . PHP_EOL; echo '> ' . $name . ' — ' . $headline . PHP_EOL; echo PHP_EOL; echo $summary . PHP_EOL; echo PHP_EOL; echo '## Machine-readable data' . PHP_EOL; echo '- JSON: ' . $site_url . 'api/data.json' . PHP_EOL; echo PHP_EOL; echo '## Links' . PHP_EOL; foreach ($nav_links as $label => $href) { echo '- ' . $label . ': ' . $href . PHP_EOL; } if (!empty($cvData['contact_links'])) { echo PHP_EOL; echo '## Contact' . PHP_EOL; foreach ($cvData['contact_links'] as $label => $href) { echo '- ' . $label . ': ' . $href . PHP_EOL; } } exit; } /** END OF MACHINE READABLE ENDPOINTS */ /** * Extract a readable URL from a href (strip protocol, trailing slash) */ function pillUrl(string $href): string { $url = $href; if (preg_match('/^[a-z]+:\/\//i', $url)) { $url = preg_replace('/^[a-z]+:\/\//i', '', $url); } $url = rtrim($url, '/'); return strlen($url) > 30 ? mb_substr($url, 0, 27) . '…' : $url; } /** * Render a standardized pill link */ function render_pill(string $href, string $label, string $icon_emoji, string $class_suffix = ''): string { $url_display = pillUrl($href); $classes = $class_suffix ? "pill {$class_suffix}" : 'pill'; return sprintf( '' . '%s' . '%s' . '%s' . '', htmlspecialchars($href, ENT_QUOTES, 'UTF-8'), $classes, $icon_emoji, htmlspecialchars($label, ENT_QUOTES, 'UTF-8'), htmlspecialchars($url_display, ENT_QUOTES, 'UTF-8') ); } /** * CV Data */ // Map experience to expected structure $cv_experience = array_map(function ($e) { return [ 'title' => $e['title'] ?? '', 'org' => $e['company'] ?? '', 'date' => $e['date'] ?? '', 'desc' => $e['description'] ?? '', ]; }, $cvData['cv']['experience'] ?? []); // Helper to calculate years between start and end dates function calculateYears($dateStr) { // Extract start and end years, support 'present' or 'current' $dateStr = str_replace(['–', '—', '−', '-'], '-', $dateStr); $parts = array_map('trim', explode('-', $dateStr, 2)); if (count($parts) < 2) { return 0; } $start = (int)$parts[0]; $endRaw = strtolower($parts[1]); $end = ($endRaw === 'present' || $endRaw === 'current') ? (int)date('Y') : (int)$endRaw; $years = $end - $start; if ($years <= 1) { return "1 year"; } return "$years years"; } // Map education to expected structure $cv_education = array_map(function ($e) { return [ 'title' => $e['degree'] ?? '', 'org' => $e['institution'] ?? '', 'date' => $e['date'] ?? '', 'desc' => $e['thesis'] ?? '', ]; }, $cvData['cv']['education'] ?? []); // Keep skills categories as provided $cv_skills = $cvData['cv']['skills'] ?? []; // JSON-LD structured data for machine readability (AI crawlers, schema.org) $jsonLd = [ '@context' => 'https://schema.org', '@type' => 'Person', 'name' => $name, 'jobTitle' => $headline, 'description' => $summary, 'url' => $site_url, 'email' => $cvData['email'] ?? '', 'telephone' => $cvData['phone'] ?? '', 'image' => $site_url . $photo_file, 'address' => [ '@type' => 'PostalAddress', 'addressLocality' => $location, ], 'sameAs' => array_values($nav_links), 'knowsAbout' => [], 'alumniOf' => [], 'worksFor' => [], ]; foreach ($cvData['cv']['skills'] ?? [] as $category => $skills) { $jsonLd['knowsAbout'] = array_merge($jsonLd['knowsAbout'], $skills); } foreach ($cvData['interests'] ?? [] as $interest) { $jsonLd['knowsAbout'][] = $interest['name'] ?? ''; } $firstExp = $cvData['cv']['experience'][0] ?? null; if ($firstExp) { $jsonLd['worksFor'] = [ '@type' => 'Organization', 'name' => str_replace('|', ' / ', $firstExp['company'] ?? ''), 'description' => $firstExp['title'] ?? '', ]; } else { unset($jsonLd['worksFor']); } foreach ($cvData['cv']['education'] ?? [] as $edu) { $jsonLd['alumniOf'][] = [ '@type' => 'CollegeOrUniversity', 'name' => $edu['institution'] ?? '', 'description' => ($edu['degree'] ?? '') . ($edu['field'] ? ' in ' . $edu['field'] : ''), ]; } $jsonLdEncoded = json_encode($jsonLd, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); /** * Page design: * - clean and simple, human-maintainable * - no dependencies * - single-file website */ ?> <?= $site_title ?>
'; } else { echo '
'; } ?>

$href): ?>
$href): ?>

Selected Work

Skills

$skills): ?>

Latest Experience

()

Past Experience

()

Education

Interests