Re-layouting
This commit is contained in:
parent
c204fc0ab8
commit
86b5743f7a
16
cv.json
16
cv.json
@ -1,6 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "David Hrdina Němeček",
|
"name": "David Hrdina Němeček",
|
||||||
"subtitle": "Software developer",
|
|
||||||
"photo": "photo.png",
|
"photo": "photo.png",
|
||||||
"email": "explosive@dejvino.cz",
|
"email": "explosive@dejvino.cz",
|
||||||
"location": "Brno, Czechia",
|
"location": "Brno, Czechia",
|
||||||
@ -113,5 +112,20 @@
|
|||||||
"Embedded",
|
"Embedded",
|
||||||
"OpenSCAD"
|
"OpenSCAD"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"highlights": [
|
||||||
|
{
|
||||||
|
"title": "Telemetry stack architecture",
|
||||||
|
"subtitle": "Shaped telemetry direction across user behavior, performance, and infrastructure for NetSuite Prime and Classic.",
|
||||||
|
"description": "Advanced OpenTelemetry delivery, Oracle APM integration paths, and OpenSearch trace visibility across multiple teams. Designed action-root hybrid sampling and trace context propagation for Classic iframe flows."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "UI performance optimizations",
|
||||||
|
"subtitle": "Designed tiered toolkit and external dependency loading for NetSuite Next startup.",
|
||||||
|
"description": "Main startup toolkit.bundle.js reduced by ~619 KB. Identified concrete improvement tracks including duplicate /myRoles calls, per-feature SSE registration, and obsolete polling."
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
"headline": "UI Platform Architect · Telemetry, Performance, and AI-Enabled Engineering",
|
||||||
|
"summary": "NetSuite UI platform engineer specializing in telemetry, observability, performance, technical design, and AI-assisted engineering enablement. Experienced in OpenTelemetry, Oracle APM, OpenSearch trace visibility, frontend/backend trace correlation, NetSuite Next performance analysis, JavaScript loading guardrails, UI-CBS contract testing, and AI interaction telemetry. Strong at turning ambiguous platform problems into validated prototypes, architecture direction, implementation plans, and handovers that help cross-functional teams execute.",
|
||||||
|
"role_summary": "UI platform architect on NetSuite Next/Prime focused on telemetry and observability architecture, performance engineering, cross-team technical design, and AI-assisted engineering enablement."
|
||||||
}
|
}
|
||||||
|
|||||||
117
index.php
117
index.php
@ -6,12 +6,23 @@
|
|||||||
$cvData = json_decode(file_get_contents(__DIR__ . '/cv.json'), true);
|
$cvData = json_decode(file_get_contents(__DIR__ . '/cv.json'), true);
|
||||||
|
|
||||||
$name = $cvData['name'] ?? '';
|
$name = $cvData['name'] ?? '';
|
||||||
$site_title = $cvData['subtitle'] ?? '';
|
$headline = $cvData['headline'] ?? '';
|
||||||
$site_url = "https://www.dejvino.cz/";
|
$summary = $cvData['summary'] ?? '';
|
||||||
$site_desc = "$name - " . ($cvData['subtitle'] ?? '');
|
$role_summary = $cvData['role_summary'] ?? '';
|
||||||
$subtitle = $cvData['subtitle'] ?? '';
|
$location = $cvData['location'] ?? '';
|
||||||
$photo_file = $cvData['photo'] ?? '';
|
$photo_file = $cvData['photo'] ?? '';
|
||||||
|
|
||||||
|
$nav_links = [
|
||||||
|
'Blog' => 'https://wp.dejvino.com/',
|
||||||
|
'Projects' => 'https://projects.dejvino.com/',
|
||||||
|
'Code' => 'https://git.dejvino.cz/',
|
||||||
|
];
|
||||||
|
$highlights = $cvData['highlights'] ?? [];
|
||||||
|
|
||||||
|
$site_url = "https://www.dejvino.cz/";
|
||||||
|
$site_title = $name;
|
||||||
|
$site_desc = "$name - $headline";
|
||||||
|
|
||||||
$mailto_link = $cvData['contact_links']['Email'] ?? '';
|
$mailto_link = $cvData['contact_links']['Email'] ?? '';
|
||||||
if (preg_match('/mailto:([^@]+)/', $mailto_link, $m)) {
|
if (preg_match('/mailto:([^@]+)/', $mailto_link, $m)) {
|
||||||
$email_user = $m[1];
|
$email_user = $m[1];
|
||||||
@ -19,16 +30,6 @@ if (preg_match('/mailto:([^@]+)/', $mailto_link, $m)) {
|
|||||||
$email_user = $cvData['email'] ?? '';
|
$email_user = $cvData['email'] ?? '';
|
||||||
}
|
}
|
||||||
|
|
||||||
$about_text = $cvData['about'] ?? [];
|
|
||||||
|
|
||||||
$nav_links = [
|
|
||||||
"~/blog" => "https://wp.dejvino.com/",
|
|
||||||
"~/projects" => "https://projects.dejvino.com/",
|
|
||||||
"~/code" => "https://git.dejvino.cz/",
|
|
||||||
];
|
|
||||||
|
|
||||||
$hardware_info = $cvData['hardware_info'] ?? '';
|
|
||||||
|
|
||||||
$extra_contact_links = $cvData['contact_links'] ?? [];
|
$extra_contact_links = $cvData['contact_links'] ?? [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -47,7 +48,6 @@ $cv_experience = array_map(function ($e) {
|
|||||||
// Helper to calculate years between start and end dates
|
// Helper to calculate years between start and end dates
|
||||||
function calculateYears($dateStr) {
|
function calculateYears($dateStr) {
|
||||||
// Extract start and end years, support 'present' or 'current'
|
// Extract start and end years, support 'present' or 'current'
|
||||||
$matches = [];
|
|
||||||
$dateStr = str_replace(['–', '—', '−', '-'], '-', $dateStr);
|
$dateStr = str_replace(['–', '—', '−', '-'], '-', $dateStr);
|
||||||
$parts = array_map('trim', explode('-', $dateStr, 2));
|
$parts = array_map('trim', explode('-', $dateStr, 2));
|
||||||
if (count($parts) < 2) {
|
if (count($parts) < 2) {
|
||||||
@ -78,7 +78,7 @@ $cv_skills = $cvData['skills'] ?? [];
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Page design:
|
* Page design:
|
||||||
* - clean and simple, human-maintaninable
|
* - clean and simple, human-maintainable
|
||||||
* - no dependencies
|
* - no dependencies
|
||||||
* - single-file website
|
* - single-file website
|
||||||
*/
|
*/
|
||||||
@ -98,7 +98,7 @@ $cv_skills = $cvData['skills'] ?? [];
|
|||||||
<meta property="og:type" content="website">
|
<meta property="og:type" content="website">
|
||||||
<meta property="og:url" content="<?= $site_url ?>">
|
<meta property="og:url" content="<?= $site_url ?>">
|
||||||
<meta property="og:title" content="<?= $name ?>">
|
<meta property="og:title" content="<?= $name ?>">
|
||||||
<meta property="og:description" content="<?= $subtitle ?>">
|
<meta property="og:description" content="<?= $headline ?>">
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
<?php
|
<?php
|
||||||
@ -111,54 +111,71 @@ $cv_skills = $cvData['skills'] ?? [];
|
|||||||
<body class="preload">
|
<body class="preload">
|
||||||
|
|
||||||
<main class="bento-grid">
|
<main class="bento-grid">
|
||||||
<section class="card profile">
|
|
||||||
|
<section class="card hero">
|
||||||
|
<div class="hero-row hero-identity">
|
||||||
<?php
|
<?php
|
||||||
if (file_exists($photo_file)) {
|
if (file_exists($photo_file)) {
|
||||||
$avatarBase64 = base64_encode(file_get_contents($photo_file));
|
$avatarBase64 = base64_encode(file_get_contents($photo_file));
|
||||||
echo '<img src="data:image/png;base64,' . $avatarBase64 . '" alt="' . $name . '" class="avatar" width="120" height="160" />';
|
echo '<img src="data:image/png;base64,' . $avatarBase64 . '" alt="' . $name . '" class="avatar" width="80" height="106" />';
|
||||||
} else {
|
} else {
|
||||||
echo '<div class="avatar-placeholder"></div>';
|
echo '<div class="avatar-placeholder"></div>';
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
<header class="header-text">
|
<div class="hero-name">
|
||||||
<h1><?= $name ?></h1>
|
<h1><?= $name ?></h1>
|
||||||
<p class="subtitle"><?= $subtitle ?></p>
|
<?php if ($headline): ?>
|
||||||
</header>
|
<p class="headline"><?= $headline ?></p>
|
||||||
</section>
|
<?php endif; ?>
|
||||||
|
<?php if ($location): ?>
|
||||||
|
<p class="location"><?= $location ?></p>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<section class="card about">
|
<?php if ($role_summary): ?>
|
||||||
<h2>Bio</h2>
|
<div class="hero-row hero-description">
|
||||||
<?php foreach ($about_text as $para): ?>
|
<p><?= $role_summary ?></p>
|
||||||
<p><?= $para ?></p>
|
</div>
|
||||||
<?php endforeach; ?>
|
<?php endif; ?>
|
||||||
</section>
|
|
||||||
|
|
||||||
<section class="card interests">
|
<div class="hero-row hero-contacts">
|
||||||
<h2>Likes</h2>
|
|
||||||
<p><?= $hardware_info ?></p>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section class="card contact">
|
|
||||||
<h2>Remote_Access</h2>
|
|
||||||
<address class="mono-addr">
|
|
||||||
Email: <span id="contact-mail">uncovering...</span>
|
|
||||||
</address>
|
|
||||||
<address class="mono-addr">
|
|
||||||
Socials:
|
|
||||||
<?php foreach ($extra_contact_links as $label => $url): ?>
|
<?php foreach ($extra_contact_links as $label => $url): ?>
|
||||||
<br><a href="<?= $url ?>" target="_blank"><?= $label ?></a>
|
<a href="<?= $url ?>" target="_blank"><?= $label ?></a>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</address>
|
</div>
|
||||||
|
|
||||||
|
<div class="hero-row hero-nav">
|
||||||
|
<?php foreach ($nav_links as $label => $url): ?>
|
||||||
|
<a href="<?= trim($url) ?>" target="_blank"><?= $label ?></a>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="card links">
|
|
||||||
<h2>Navigation</h2>
|
<?php if ($summary): ?>
|
||||||
<ul class="link-grid">
|
<section class="card summary">
|
||||||
<?php foreach ($nav_links as $label => $url): ?>
|
<h2>Summary</h2>
|
||||||
<li><a href="<?= trim($url) ?>" target="_blank"><span><?= $label ?></span></a></li>
|
<p><?= $summary ?></p>
|
||||||
<?php endforeach; ?>
|
|
||||||
</ul>
|
|
||||||
</section>
|
</section>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php if ($highlights): ?>
|
||||||
|
<section class="card selected-work">
|
||||||
|
<h2>Selected Work</h2>
|
||||||
|
<?php foreach ($highlights as $h): ?>
|
||||||
|
<article class="highlight-item">
|
||||||
|
<h3><?= $h['title'] ?? '' ?></h3>
|
||||||
|
<?php if ($h['subtitle'] ?? ''): ?>
|
||||||
|
<p class="highlight-subtitle"><?= $h['subtitle'] ?></p>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php if ($h['description'] ?? ''): ?>
|
||||||
|
<p class="highlight-description"><?= $h['description'] ?></p>
|
||||||
|
<?php endif; ?>
|
||||||
|
</article>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</section>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
<section class="card cv-container">
|
<section class="card cv-container">
|
||||||
<label class="cv-header" for="cv-toggle">
|
<label class="cv-header" for="cv-toggle">
|
||||||
|
|||||||
88
style.css
88
style.css
@ -74,7 +74,7 @@ body {
|
|||||||
|
|
||||||
.bento-grid {
|
.bento-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
max-width: 800px;
|
max-width: 1000px;
|
||||||
gap: 24px;
|
gap: 24px;
|
||||||
grid-template-columns: repeat(3, 1fr);
|
grid-template-columns: repeat(3, 1fr);
|
||||||
}
|
}
|
||||||
@ -122,15 +122,13 @@ body {
|
|||||||
filter: none !important;
|
filter: none !important;
|
||||||
margin-right: 16px !important;
|
margin-right: 16px !important;
|
||||||
}
|
}
|
||||||
.profile { grid-column: span 3; }
|
.hero { grid-column: span 3; }
|
||||||
.about { grid-column: span 2; }
|
|
||||||
.interests { grid-column: span 1; }
|
|
||||||
.contact { grid-column: span 1; }
|
|
||||||
.links { grid-column: span 2; }
|
|
||||||
.hiring-toggle { grid-column: span 3; }
|
.hiring-toggle { grid-column: span 3; }
|
||||||
|
.summary { grid-column: span 3; }
|
||||||
|
.selected-work { grid-column: span 3; }
|
||||||
.cv-container { grid-column: span 3; }
|
.cv-container { grid-column: span 3; }
|
||||||
.experience { grid-column: span 2; }
|
.experience { grid-column: span 3; }
|
||||||
.skills { grid-column: span 1; }
|
.skills { grid-column: span 3; }
|
||||||
.education { grid-column: span 3; }
|
.education { grid-column: span 3; }
|
||||||
|
|
||||||
/* Shuffle Logic */
|
/* Shuffle Logic */
|
||||||
@ -144,11 +142,9 @@ body {
|
|||||||
filter: none !important;
|
filter: none !important;
|
||||||
margin-right: 16px !important;
|
margin-right: 16px !important;
|
||||||
}
|
}
|
||||||
.profile { transform: rotate(0.1deg); }
|
.hero { transform: rotate(0.1deg); }
|
||||||
.about { transform: translate(-4px, 2px) rotate(-0.5deg); }
|
.summary { transform: translate(-2px, 2px) rotate(-0.3deg); }
|
||||||
.interests { transform: translate(6px, -2px) rotate(0.4deg); }
|
.selected-work { transform: translate(2px, -2px) rotate(-0.2deg); }
|
||||||
.links { transform: translate(-2px, -4px) rotate(-0.3deg); }
|
|
||||||
.contact { transform: translate(4px, 6px) rotate(0.5deg); }
|
|
||||||
.hiring-toggle { transform: translate(-2px, 3px) rotate(0.2deg); }
|
.hiring-toggle { transform: translate(-2px, 3px) rotate(0.2deg); }
|
||||||
.experience { transform: translate(3px, -2px) rotate(-0.2deg); }
|
.experience { transform: translate(3px, -2px) rotate(-0.2deg); }
|
||||||
.skills { transform: translate(-3px, 4px) rotate(0.6deg); }
|
.skills { transform: translate(-3px, 4px) rotate(0.6deg); }
|
||||||
@ -174,6 +170,70 @@ body {
|
|||||||
|
|
||||||
.profile { display: flex; align-items: center; gap: 32px; }
|
.profile { display: flex; align-items: center; gap: 32px; }
|
||||||
|
|
||||||
|
.hero {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
.hero-identity {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
.hero-name {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
.hero-name h1 {
|
||||||
|
margin: 0 0 4px 0;
|
||||||
|
}
|
||||||
|
.hero-name .headline {
|
||||||
|
margin: 0 0 4px 0;
|
||||||
|
font-size: 1rem;
|
||||||
|
color: var(--accent-color);
|
||||||
|
}
|
||||||
|
.hero-name .location {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
.hero-description {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.hero-description p {
|
||||||
|
margin: 0;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
.hero-contacts {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
.hero-contacts a {
|
||||||
|
color: var(--link-color);
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
.hero-contacts a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
.hero-nav {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 12px;
|
||||||
|
padding-top: 8px;
|
||||||
|
border-top: 1px solid rgba(0, 243, 255, 0.15);
|
||||||
|
}
|
||||||
|
.hero-nav a {
|
||||||
|
color: var(--text-color);
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
.hero-nav a:hover {
|
||||||
|
opacity: 1;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
.hiring-toggle {
|
.hiring-toggle {
|
||||||
padding: 12px 24px;
|
padding: 12px 24px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@ -477,6 +537,8 @@ a { color: var(--link-color); text-decoration: none; }
|
|||||||
margin-right: 16px !important;
|
margin-right: 16px !important;
|
||||||
}
|
}
|
||||||
.profile { flex-direction: column; text-align: center; }
|
.profile { flex-direction: column; text-align: center; }
|
||||||
|
.hero { flex-direction: column; text-align: center; }
|
||||||
|
.hero-identity { flex-direction: column; text-align: center; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Print mode */
|
/* Print mode */
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user