173 lines
12 KiB
PHP
173 lines
12 KiB
PHP
<?php
|
|
/* Page « Compétences » (/competences/, ancienne adresse /services/ redirigée en 301) */
|
|
get_header();
|
|
$services = yb2026_profile('yb_services');
|
|
|
|
/* Chiffres calculés en direct */
|
|
$nb_real = (int) wp_count_posts('realisation')->publish;
|
|
$nb_posts = (int) wp_count_posts('post')->publish;
|
|
|
|
/* Boîte à outils : uniquement ce que prouvent les réalisations, articles et le poste */
|
|
$toolbox = array(
|
|
array('t' => 'Développement web', 'i' => array('PHP 8', 'Symfony', 'Twig Components', 'Doctrine', 'WordPress sur mesure', 'PHP/MVC sans framework', 'JavaScript vanilla', 'HTML / CSS responsive')),
|
|
array('t' => 'Données & outillage', 'i' => array('MariaDB / MySQL', 'PostgreSQL', 'SQL', 'API HTTP / JSON', 'Python 3', 'Node.js', 'JS ESM', 'FFmpeg', 'librsvg')),
|
|
array('t' => 'Systèmes & conteneurs', 'i' => array('Debian 12', 'Docker / Compose', 'systemd', 'Apache', 'Nginx Proxy Manager', 'TLS Let\'s Encrypt', 'Réglage mémoire JVM')),
|
|
array('t' => 'Réseau & sécurité', 'i' => array('VLAN', 'DNS', 'DHCP', 'WireGuard', 'Pi-hole', 'Active Directory', 'Reverse proxy', 'Services privés par défaut')),
|
|
array('t' => 'Support & MCO', 'i' => array('Diagnostic d\'incidents', 'Lecture de logs', 'Accompagnement utilisateurs', 'Procédures documentées', 'Supervision Uptime Kuma', 'Sauvegardes planifiées')),
|
|
array('t' => 'Outils du quotidien', 'i' => array('Git', 'Forgejo / Gitea', 'GitHub', 'VS Code / code-server', 'Terminal & SSH')),
|
|
);
|
|
|
|
/* Méthode : tirée de mes retours d'expérience (OOM killer, faux bug, servyass) */
|
|
$method = array(
|
|
array('t' => 'Observer', 'd' => 'Lire les journaux en entier, reproduire le symptôme, noter ce qui change et ce qui ne change pas.'),
|
|
array('t' => 'Isoler', 'd' => 'Réduire le périmètre : environnement, ressources, configuration, code. Vérifier aussi l\'outil de mesure.'),
|
|
array('t' => 'Corriger', 'd' => 'Formuler une hypothèse, la tester, appliquer le correctif le plus simple qui traite la vraie cause.'),
|
|
array('t' => 'Documenter', 'd' => 'Écrire la procédure, pour que la même panne se règle en cinq minutes la prochaine fois.'),
|
|
);
|
|
|
|
/* Preuves : gérées dans l'admin (Profil → Compétences), voir inc/proofs.php */
|
|
$proofs = yb2026_get_proofs();
|
|
|
|
$containers = array('npm', 'jellyfin', 'forgejo', 'code-server', 'wordpress + mariadb', 'passbolt + mariadb', 'poste.io', 'uptime-kuma', 'filebrowser · alist', 'wireguard');
|
|
$infra_points = array(
|
|
array('t' => 'Pas un lab jetable', 'd' => 'De la prod perso avec de vrais utilisateurs, de vraies pannes et de vrais correctifs. Si Jellyfin tombe, on me le fait savoir.'),
|
|
array('t' => 'Incidents gérés', 'd' => 'OOM, conflits de ports, migration complète de matériel, watchdog réseau, certificats TLS : diagnostiqués et résolus seul.'),
|
|
array('t' => 'Méthode', 'd' => 'Supervision Uptime Kuma, sauvegardes planifiées, mises à jour de sécurité régulières, procédures documentées.'),
|
|
);
|
|
?>
|
|
|
|
|
|
<div class="cp">
|
|
|
|
<!-- ── Ouverture : titre + phrase manifeste aux chiffres animés ─────── -->
|
|
<section class="cp-open page-wrap">
|
|
<div class="kicker">CE QUE JE SAIS FAIRE</div>
|
|
<h1 class="cp-title" data-reveal>COMPÉ<span class="outline-lime">TENCES</span></h1>
|
|
<p class="cp-manifest" data-reveal>
|
|
J'ai livré <span class="cp-num" data-count="<?php echo (int) $nb_real; ?>" data-pad="2"><?php echo esc_html(str_pad($nb_real, 2, '0', STR_PAD_LEFT)); ?></span> projets,
|
|
écrit <span class="cp-num" data-count="<?php echo (int) $nb_posts; ?>" data-pad="2"><?php echo esc_html(str_pad($nb_posts, 2, '0', STR_PAD_LEFT)); ?></span> articles techniques,
|
|
et je fais tourner <span class="cp-num" data-count="37">37</span> services en production
|
|
depuis <span class="cp-num" data-count="2" data-suffix=" ans">2 ans</span>.
|
|
</p>
|
|
</section>
|
|
|
|
<!-- ── Services : lignes éditoriales, rideau lime au survol ─────────── -->
|
|
<section class="cp-svc" aria-label="Services">
|
|
<?php foreach ($services as $i => $sv) : ?>
|
|
<div class="cp-svc__row" data-reveal>
|
|
<span class="cp-svc__n"><?php echo esc_html(str_pad($i + 1, 2, '0', STR_PAD_LEFT)); ?></span>
|
|
<h2 class="cp-svc__t"><?php echo esc_html($sv['titre']); ?></h2>
|
|
<p class="cp-svc__d"><?php echo esc_html($sv['desc']); ?></p>
|
|
</div>
|
|
<?php endforeach; ?>
|
|
</section>
|
|
|
|
<!-- ── Boîte à outils : un bandeau défilant géant par domaine ───────── -->
|
|
<section class="cp-tools" aria-label="Boîte à outils">
|
|
<div class="page-wrap cp-head">
|
|
<div class="kicker">BOÎTE À OUTILS</div>
|
|
<h2 class="cp-h" data-reveal>CE QUE <span class="outline-lime">J'UTILISE</span></h2>
|
|
</div>
|
|
<?php foreach ($toolbox as $i => $tb) : ?>
|
|
<div class="cp-tools__row<?php echo $i % 2 ? ' is-alt' : ''; ?>">
|
|
<div class="cp-tools__label"><span class="lime"><?php echo esc_html(str_pad($i + 1, 2, '0', STR_PAD_LEFT)); ?></span> <?php echo esc_html(mb_strtoupper($tb['t'])); ?></div>
|
|
<div class="marquee cp-tools__mq" aria-label="<?php echo esc_attr(implode(', ', $tb['i'])); ?>">
|
|
<div class="marquee-track<?php echo $i % 2 ? ' marquee-track--reverse' : ''; ?>" style="--dur:<?php echo 26 + $i * 3; ?>s" aria-hidden="true">
|
|
<?php for ($k = 0; $k < 2; $k++) : ?>
|
|
<span><?php foreach ($tb['i'] as $j => $tool) : ?><b class="<?php echo ($j + $i) % 2 ? 'is-outline' : ''; ?>"><?php echo esc_html(mb_strtoupper($tool)); ?></b><i class="lime">✦</i><?php endforeach; ?></span>
|
|
<?php endfor; ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<?php endforeach; ?>
|
|
</section>
|
|
|
|
<!-- ── Méthode : numéro géant fixé, étapes qui défilent ─────────────── -->
|
|
<section class="cp-method page-wrap" aria-label="Ma méthode">
|
|
<div class="cp-method__aside">
|
|
<div class="kicker">MA MÉTHODE</div>
|
|
<h2 class="cp-h">QUAND ÇA <span class="outline-lime">CASSE</span></h2>
|
|
<div class="cp-method__big" aria-hidden="true">
|
|
<?php foreach ($method as $i => $m) : ?>
|
|
<span class="cp-method__num<?php echo $i === 0 ? ' is-on' : ''; ?>" data-step="<?php echo $i; ?>"><?php echo esc_html(str_pad($i + 1, 2, '0', STR_PAD_LEFT)); ?></span>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
</div>
|
|
<ol class="cp-method__steps">
|
|
<?php foreach ($method as $i => $m) : ?>
|
|
<li class="cp-method__step<?php echo $i === 0 ? ' is-on' : ''; ?>" data-step="<?php echo $i; ?>">
|
|
<span class="cp-method__k"><?php echo esc_html(str_pad($i + 1, 2, '0', STR_PAD_LEFT)); ?> / <?php echo esc_html(str_pad(count($method), 2, '0', STR_PAD_LEFT)); ?></span>
|
|
<span class="cp-method__t"><?php echo esc_html(mb_strtoupper($m['t'])); ?></span>
|
|
<span class="cp-method__d"><?php echo esc_html($m['d']); ?></span>
|
|
</li>
|
|
<?php endforeach; ?>
|
|
</ol>
|
|
</section>
|
|
|
|
<!-- ── Infra servyass (terminal du design d'origine) ────────────────── -->
|
|
<section class="page-wrap cp-infra">
|
|
<div class="kicker">$ ssh yass@servyass</div>
|
|
<h2 class="infra-title" data-reveal>L'INFRA <span class="lime">SERVYASS</span> · EN PROD DEPUIS 2 ANS</h2>
|
|
<p class="infra-lead">Je ne me contente pas de lister des compétences : 2 ans d'infrastructure Linux/Docker auto-hébergée, administrée seul, en production réelle. Debian 12 · Docker Engine · Ryzen 3 3200G · 13 GB RAM.</p>
|
|
<div class="infra-cols">
|
|
<div class="term" data-reveal>
|
|
<div class="term-bar">
|
|
<span class="term-dot term-dot--r"></span><span class="term-dot term-dot--y"></span><span class="term-dot term-dot--g"></span>
|
|
<span class="term-title">yass@servyass: docker ps</span>
|
|
</div>
|
|
<div class="term-body">
|
|
<div class="term-muted">$ docker ps --format table · NAME · STATUS</div>
|
|
<?php foreach ($containers as $c) : ?>
|
|
<div class="term-row"><span><?php echo esc_html($c); ?></span><span class="lime">Up (healthy)</span></div>
|
|
<?php endforeach; ?>
|
|
<div class="term-muted term-foot">$ uptime · ▲ en production depuis 2 ans, maintenu en autonomie</div>
|
|
</div>
|
|
</div>
|
|
<div class="infra-points">
|
|
<?php foreach ($infra_points as $ip) : ?>
|
|
<div class="ipoint" data-reveal>
|
|
<div class="ipoint-title"><?php echo esc_html($ip['t']); ?></div>
|
|
<div class="ipoint-desc"><?php echo esc_html($ip['d']); ?></div>
|
|
</div>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
</div>
|
|
<div class="infra-strip">FLUX EN DIRECT · 16+ CONTENEURS · 1 SEUL ADMIN · SUPERVISION UPTIME-KUMA · BACKUPS PLANIFIÉS · MÀJ SÉCU HEBDO</div>
|
|
</section>
|
|
|
|
<!-- ── Preuves : survol d'une compétence = vignette du projet qui suit la souris ── -->
|
|
<?php if ($proofs) : ?>
|
|
<section class="cp-proofs" aria-label="Preuves">
|
|
<div class="page-wrap cp-head">
|
|
<div class="kicker">PREUVES À L'APPUI · PROJETS & ARTICLES</div>
|
|
<h2 class="cp-h" data-reveal>CHAQUE COMPÉTENCE <span class="outline-lime">A SON PROJET</span></h2>
|
|
</div>
|
|
<ul class="cp-proofs__list">
|
|
<?php foreach ($proofs as $skill => $links) :
|
|
$first = $links[0]; ?>
|
|
<li class="cp-proof" data-thumb="<?php echo esc_url($first['thumb']); ?>" data-name="<?php echo esc_attr($first['name']); ?>" data-cursor-label="<?php echo count($links) > 1 ? 'OUVRIR LA ROUE' : ($first['kind'] === 'article' ? 'LIRE L\'ARTICLE' : 'VOIR LE PROJET'); ?>">
|
|
<span class="cp-proof__skill"><?php echo esc_html($skill); ?></span>
|
|
<span class="cp-proof__links">
|
|
<?php foreach ($links as $l) : ?>
|
|
<a href="<?php echo esc_url(get_permalink($l['post'])); ?>" class="is-<?php echo esc_attr($l['kind']); ?>" data-wipe="<?php echo esc_attr($l['wipe']); ?>" data-cursor-label="<?php echo $l['kind'] === 'article' ? 'LIRE L\'ARTICLE' : 'VOIR LE PROJET'; ?>" data-thumb="<?php echo esc_url($l['thumb']); ?>" data-name="<?php echo esc_attr($l['name']); ?>" data-kind="<?php echo esc_attr($l['kind']); ?>" data-tag="<?php echo esc_attr($l['tag']); ?>"><?php if ($l['kind'] === 'article') : ?><span class="cp-proof__kind">ARTICLE</span> <?php endif; ?><?php echo esc_html($l['name']); ?> <span class="lime">→</span></a>
|
|
<?php endforeach; ?>
|
|
</span>
|
|
</li>
|
|
<?php endforeach; ?>
|
|
</ul>
|
|
<div class="cp-preview" aria-hidden="true"></div>
|
|
<div class="cp-wheel" hidden role="dialog" aria-label="Choisir un projet">
|
|
<div class="cp-wheel__svg" aria-hidden="true"></div>
|
|
<div class="cp-wheel__center"><span class="cp-wheel__skill"></span><span class="cp-wheel__name"></span><span class="cp-wheel__hint"></span></div>
|
|
</div>
|
|
</section>
|
|
<?php endif; ?>
|
|
|
|
<!-- ── Fin : appel à l'échange, comme sur l'accueil ─────────────────── -->
|
|
<section class="cta">
|
|
<div class="kicker" data-reveal><?php echo esc_html(mb_strtoupper(yb2026_id('accroche'))); ?></div>
|
|
<a class="cta__title" href="<?php echo esc_url(home_url('/contact/')); ?>" data-wipe="CONTACT" data-cursor-label="M'ÉCRIRE" data-reveal>TRAVAILLONS<br><span class="outline-lime">ENSEMBLE →</span></a>
|
|
</section>
|
|
</div>
|
|
|
|
<?php get_footer(); ?>
|