Fixup machine endpoints
This commit is contained in:
parent
4cb4b645ef
commit
86b20b2ce5
@ -31,6 +31,9 @@ RewriteRule ^domains/[^/]+/(.+[^/])$ /$1/ [R]
|
|||||||
RewriteCond %{REQUEST_FILENAME} -d
|
RewriteCond %{REQUEST_FILENAME} -d
|
||||||
RewriteRule ^subdom/[^/]+/(.+[^/])$ /$1/ [R]
|
RewriteRule ^subdom/[^/]+/(.+[^/])$ /$1/ [R]
|
||||||
|
|
||||||
|
# Route /api/data.json and /llms.txt to index.php for machine-readable data
|
||||||
|
RewriteRule ^(api/data\.json|llms\.txt)$ index.php [L,QSA]
|
||||||
|
|
||||||
# Route /cv to index.php for CV view
|
# Route /cv to index.php for CV view
|
||||||
RewriteCond %{REQUEST_FILENAME} !-f
|
RewriteCond %{REQUEST_FILENAME} !-f
|
||||||
RewriteCond %{REQUEST_FILENAME} !-d
|
RewriteCond %{REQUEST_FILENAME} !-d
|
||||||
|
|||||||
18
data.json
18
data.json
@ -9,7 +9,7 @@
|
|||||||
"contact_links": {
|
"contact_links": {
|
||||||
"Website": "https://www.dejvino.cz",
|
"Website": "https://www.dejvino.cz",
|
||||||
"Email": "mailto:explosive@dejvino.cz",
|
"Email": "mailto:explosive@dejvino.cz",
|
||||||
"Resume": "https://dejvino.cz/cv"
|
"Resume": "https://www.dejvino.cz/cv"
|
||||||
},
|
},
|
||||||
"about": [
|
"about": [
|
||||||
"Principal Software Engineer at Oracle NetSuite, focusing on AI-assisted developer enablement, UI platform architecture, performance, and observability for 40k+ enterprise customers."
|
"Principal Software Engineer at Oracle NetSuite, focusing on AI-assisted developer enablement, UI platform architecture, performance, and observability for 40k+ enterprise customers."
|
||||||
@ -153,33 +153,27 @@
|
|||||||
"interests": [
|
"interests": [
|
||||||
{
|
{
|
||||||
"name": "Mandolin",
|
"name": "Mandolin",
|
||||||
"caption": "Octave mandolin is my instrument of choice. Wide range of tones, pleasant sound. Great way to relax your mind, explore melodies and harmonies.",
|
"caption": "Octave mandolin is my instrument of choice. Wide range of tones, pleasant sound. Great way to relax your mind, explore melodies and harmonies."
|
||||||
"image": null
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Electronics tinkering",
|
"name": "Electronics tinkering",
|
||||||
"caption": "Building a useful device from scratch. Retrofitting modern brains into a broken vintage shell. Electronics is the magic that makes things alive.",
|
"caption": "Building a useful device from scratch. Retrofitting modern brains into a broken vintage shell. Electronics is the magic that makes things alive."
|
||||||
"image": null
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Synthwave",
|
"name": "Synthwave",
|
||||||
"caption": "Neon-filled nostalgia. Fun to create, relaxing to listen to it.",
|
"caption": "Neon-filled nostalgia. Fun to create, relaxing to listen to it.",
|
||||||
"image": "interests/synthwave.png"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "3D Printing & Design",
|
"name": "3D Printing & Design",
|
||||||
"caption": "Designing and printing custom parts that serve a purpose. Unique designs, useful accessories, toys or just repairs.",
|
"caption": "Designing and printing custom parts that serve a purpose. Unique designs, useful accessories, toys or just repairs."
|
||||||
"image": null
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Mountain Biking",
|
"name": "Mountain Biking",
|
||||||
"caption": "Going places under your own power. Exploring forests, trails and nature where cars aren't allowed.",
|
"caption": "Going places under your own power. Exploring forests, trails and nature where cars aren't allowed."
|
||||||
"image": null
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "RC Cars",
|
"name": "RC Cars",
|
||||||
"caption": "Rock crawlers, construction trucks, military vehicles. Building a custom offroad course in the garden to trial them all.",
|
"caption": "Rock crawlers, construction trucks, military vehicles. Building a custom offroad course in the garden to trial them all."
|
||||||
"image": null
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
94
index.php
94
index.php
@ -40,13 +40,6 @@ $site_url = "https://www.dejvino.cz/";
|
|||||||
$site_title = $name;
|
$site_title = $name;
|
||||||
$site_desc = "$name - $headline";
|
$site_desc = "$name - $headline";
|
||||||
|
|
||||||
$mailto_link = $cvData['contact_links']['Email'] ?? '';
|
|
||||||
if (preg_match('/mailto:([^@]+)/', $mailto_link, $m)) {
|
|
||||||
$email_user = $m[1];
|
|
||||||
} else {
|
|
||||||
$email_user = $cvData['email'] ?? '';
|
|
||||||
}
|
|
||||||
|
|
||||||
$extra_contact_links = $cvData['contact_links'] ?? [];
|
$extra_contact_links = $cvData['contact_links'] ?? [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -65,6 +58,39 @@ $pill_icons = [
|
|||||||
'GitHub' => '🐙',
|
'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)
|
* Extract a readable URL from a href (strip protocol, trailing slash)
|
||||||
*/
|
*/
|
||||||
@ -142,6 +168,51 @@ $cv_education = array_map(function ($e) {
|
|||||||
// Keep skills categories as provided
|
// Keep skills categories as provided
|
||||||
$cv_skills = $cvData['cv']['skills'] ?? [];
|
$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:
|
* Page design:
|
||||||
* - clean and simple, human-maintainable
|
* - clean and simple, human-maintainable
|
||||||
@ -166,6 +237,8 @@ $cv_skills = $cvData['cv']['skills'] ?? [];
|
|||||||
<meta property="og:title" content="<?= $name ?>">
|
<meta property="og:title" content="<?= $name ?>">
|
||||||
<meta property="og:description" content="<?= $headline ?>">
|
<meta property="og:description" content="<?= $headline ?>">
|
||||||
|
|
||||||
|
<script type="application/ld+json"><?= $jsonLdEncoded ?></script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
<?php
|
<?php
|
||||||
include 'style.css';
|
include 'style.css';
|
||||||
@ -322,13 +395,6 @@ $cv_skills = $cvData['cv']['skills'] ?? [];
|
|||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script>
|
|
||||||
((u, d, t) => {
|
|
||||||
const addr = (atob(u) + '@' + d + '.' + t).trim();
|
|
||||||
const el = document.getElementById("contact-mail");
|
|
||||||
if (el) el.innerHTML = `<a href="mailto:${addr}">${addr}</a>`;
|
|
||||||
})('<?= base64_encode($email_user) ?>', 'dejvino', 'cz');
|
|
||||||
</script>
|
|
||||||
<!-- Cloudflare Web Analytics -->
|
<!-- Cloudflare Web Analytics -->
|
||||||
<script defer src='https://static.cloudflareinsights.com/beacon.min.js' data-cf-beacon='{"token": "90827cb740cd4b1db611be059f64daa9"}'></script><!-- End Cloudflare Web Analytics -->
|
<script defer src='https://static.cloudflareinsights.com/beacon.min.js' data-cf-beacon='{"token": "90827cb740cd4b1db611be059f64daa9"}'></script><!-- End Cloudflare Web Analytics -->
|
||||||
<?php $file_mod_time = filemtime(__FILE__); ?>
|
<?php $file_mod_time = filemtime(__FILE__); ?>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user