DOC
2026 04 09 site refonte
Site Refonte — Swiss + Use Cases Implementation Plan
For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (
- [ ]) syntax for tracking.
Goal: Réécrire site/index.html avec un design Swiss International Style (navy #02065D + orange #FF9A04), layout split asymétrique, 10 use cases expandables, grille agents filtrables, animations géométriques — stack HTML + Tailwind CDN + Alpine.js.
Architecture: Single HTML file self-contained. Alpine.js pour l’interactivité (expand use cases, filtres agents, copy, modal). site/data/commands.json existant réutilisé pour la grille agents. Modal fetch GitHub raw inchangé.
Tech Stack: HTML5, Tailwind CSS CDN v3, Alpine.js CDN, IBM Plex Mono (Google Fonts), Iconify CDN
Files
| Fichier | Action |
|---|---|
site/index.html | Réécriture complète |
site/data/commands.json | Inchangé |
Task 1 : Foundation — head, palette, CSS custom, squelette
Files:
-
Modify:
site/index.html(réécriture complète) -
Step 1 : Vérifier le fichier actuel
wc -l /Users/izo/Dev/Docs/Ulk/site/index.html
Expected : ~1636 lignes.
- Step 2 : Écrire le nouveau fichier avec foundation complète
Écrire exactement ce contenu à /Users/izo/Dev/Docs/Ulk/site/index.html :
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ulk — AI Development Toolkit for Claude Code</title>
<meta name="description" content="71 agents IA spécialisés pour Claude Code. Zéro config, mémoire inter-sessions, CLI-first.">
<link rel="icon" href="https://raw.githubusercontent.com/izo/Ulk/main/ulk.png" type="image/png">
<!-- Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;700;900&family=IBM+Plex+Sans:wght@400;500;700&display=swap" rel="stylesheet">
<!-- Tailwind -->
<script src="https://cdn.tailwindcss.com"></script>
<script>
tailwind.config = {
theme: {
extend: {
colors: {
navy: '#02065D',
'navy-dark': '#01043d',
'navy-deeper': '#010230',
swiss: '#FF9A04',
'swiss-muted': 'rgba(255,154,4,0.15)',
},
fontFamily: {
mono: ['IBM Plex Mono', 'monospace'],
sans: ['IBM Plex Sans', 'system-ui', 'sans-serif'],
},
animation: {
'pulse-slow': 'pulse-slow 4s cubic-bezier(0.4,0,0.6,1) infinite',
'spin-slow': 'spin 12s linear infinite',
'type-1': 'typing 0.5s steps(12,end) 0.3s both',
'type-2': 'typing 0.5s steps(15,end) 1.4s both',
'type-3': 'typing 0.5s steps(10,end) 2.5s both',
},
keyframes: {
'pulse-slow': {
'0%,100%': { transform: 'scale(1)', opacity: '0.85' },
'50%': { transform: 'scale(1.06)', opacity: '1' },
},
'typing': {
from: { width: '0', opacity: '0' },
to: { width: '100%', opacity: '1' },
},
},
}
}
}
</script>
<!-- Alpine.js -->
<script defer src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js"></script>
<!-- Iconify -->
<script src="https://code.iconify.design/3/3.1.1/iconify.min.js"></script>
<style>
/* Base */
*, *::before, *::after { box-sizing: border-box; }
body { background: #02065D; color: #fff; font-family: 'IBM Plex Mono', monospace; }
/* Swiss geometric circle */
.swiss-circle {
border-radius: 50%;
background: #FF9A04;
animation: pulse-slow 4s cubic-bezier(0.4,0,0.6,1) infinite;
}
.swiss-circle-ring {
border-radius: 50%;
border: 3px solid #FF9A04;
animation: pulse-slow 4s cubic-bezier(0.4,0,0.6,1) infinite 0.5s;
}
/* Split layout */
.split-left {
position: sticky;
top: 0;
height: 100vh;
background: #02065D;
border-right: 3px solid #FF9A04;
display: flex;
flex-direction: column;
justify-content: space-between;
padding: 2rem;
}
/* Use case row */
.use-case-row {
border-bottom: 1px solid rgba(255,255,255,0.06);
transition: all 0.2s ease;
}
.use-case-row:hover { background: rgba(255,154,4,0.04); }
.use-case-row.open { border-left: 3px solid #FF9A04; background: rgba(255,154,4,0.06); }
/* Agent card */
.agent-card {
background: rgba(255,255,255,0.03);
border: 1px solid rgba(255,255,255,0.08);
border-radius: 8px;
transition: all 0.2s ease;
cursor: pointer;
}
.agent-card:hover {
background: rgba(255,154,4,0.06);
border-color: rgba(255,154,4,0.3);
}
/* Filter pill */
.filter-pill {
border: 1px solid rgba(255,255,255,0.15);
border-radius: 99px;
padding: 4px 14px;
font-size: 11px;
cursor: pointer;
transition: all 0.15s;
white-space: nowrap;
}
.filter-pill:hover, .filter-pill.active {
background: #FF9A04;
border-color: #FF9A04;
color: #000;
font-weight: 700;
}
/* Code block */
.code-block {
background: #010230;
border: 1px solid rgba(255,154,4,0.2);
border-radius: 8px;
font-family: 'IBM Plex Mono', monospace;
font-size: 13px;
}
/* Modal */
.modal-backdrop {
position: fixed; inset: 0;
background: rgba(1,2,45,0.85);
backdrop-filter: blur(4px);
z-index: 50;
display: flex; align-items: center; justify-content: center;
}
.modal-panel {
background: #01043d;
border: 1px solid rgba(255,154,4,0.2);
border-radius: 12px;
width: min(720px, 95vw);
max-height: 80vh;
overflow-y: auto;
}
/* Terminal typing lines */
.terminal-line {
overflow: hidden;
white-space: nowrap;
display: block;
}
.terminal-line-1 { animation: typing 0.4s steps(18,end) 0.4s both; }
.terminal-line-2 { animation: typing 0.4s steps(14,end) 1.2s both; }
.terminal-line-3 { animation: typing 0.4s steps(12,end) 2.0s both; }
/* Swiss section header */
.section-header {
display: flex;
align-items: center;
gap: 1rem;
padding: 2rem 0 1.5rem;
border-bottom: 2px solid #FF9A04;
margin-bottom: 2rem;
}
.section-header-label {
font-size: 11px;
letter-spacing: 0.15em;
text-transform: uppercase;
color: #FF9A04;
font-weight: 700;
}
.section-header-num {
font-size: 11px;
color: rgba(255,255,255,0.3);
margin-left: auto;
}
/* Scrollbar */
::-webkit-scrollbar { width: 4px; }
::-webkit-scrollbar-track { background: #01043d; }
::-webkit-scrollbar-thumb { background: rgba(255,154,4,0.3); border-radius: 2px; }
/* Mobile */
@media (max-width: 768px) {
.split-left { position: relative; height: auto; }
.desktop-only { display: none; }
}
</style>
</head>
<body x-data="ulkApp()" x-init="init()">
<!-- NAV -->
<nav id="nav" style="background:#01043d; border-bottom:1px solid rgba(255,154,4,0.2);"
class="sticky top-0 z-50 flex items-center justify-between px-6 py-3">
<div class="flex items-center gap-3">
<span class="font-mono font-black text-white text-lg tracking-tight">ulk</span>
<span class="text-xs font-mono px-2 py-0.5 rounded"
style="background:rgba(255,154,4,0.12); color:#FF9A04; border:1px solid rgba(255,154,4,0.2);">
v3.5.0
</span>
</div>
<div class="flex items-center gap-6">
<a href="#use-cases" class="text-xs font-mono text-white/50 hover:text-swiss transition-colors hidden md:block">Use Cases</a>
<a href="#agents" class="text-xs font-mono text-white/50 hover:text-swiss transition-colors hidden md:block">Agents</a>
<a href="#install" class="text-xs font-mono text-white/50 hover:text-swiss transition-colors hidden md:block">Install</a>
<a href="https://github.com/izo/ulk" target="_blank"
class="text-xs font-mono px-3 py-1.5 rounded transition-all"
style="background:#FF9A04; color:#000; font-weight:700;">
GitHub →
</a>
</div>
</nav>
<!-- HERO -->
<section class="min-h-screen md:grid" style="grid-template-columns: 38% 62%;">
<!-- Left col — Swiss identity -->
<div class="split-left">
<div class="text-xs font-mono tracking-widest uppercase" style="color:rgba(255,255,255,0.3);">
AI Development Toolkit
</div>
<div>
<div class="font-mono font-black leading-none mb-6" style="font-size:clamp(3rem,8vw,5.5rem);">
<div class="text-white">AI</div>
<div class="text-white">Dev</div>
<div style="color:#FF9A04;">ulk.</div>
</div>
<div class="flex gap-3">
<div class="swiss-circle" style="width:48px;height:48px;"></div>
<div class="swiss-circle-ring" style="width:48px;height:48px;"></div>
<div style="width:48px;height:48px;border-radius:50%;background:rgba(255,154,4,0.2);"></div>
</div>
</div>
<div>
<div class="text-xs font-mono mb-1" style="color:rgba(255,255,255,0.3);">
71 agents · zero config
</div>
<div class="text-xs font-mono" style="color:rgba(255,255,255,0.3);">
ships today
</div>
</div>
</div>
<!-- Right col — Tagline + Install -->
<div class="flex flex-col justify-center px-8 md:px-16 py-16" style="background:#01043d;">
<div class="text-xs font-mono tracking-widest uppercase mb-6" style="color:#FF9A04;">
for Claude Code
</div>
<h1 class="font-sans font-black mb-4 text-white leading-tight"
style="font-size:clamp(2rem,5vw,3.5rem);">
Ship faster.<br>
<span style="color:rgba(255,255,255,0.4);">Think less.</span>
</h1>
<p class="font-sans text-base mb-10" style="color:rgba(255,255,255,0.55); max-width:480px;">
71 agents IA spécialisés qui détectent votre stack, orchestrent le travail, et committent proprement.
Bruce s'en charge. Vous tapez une commande.
</p>
<!-- Terminal animation -->
<div class="code-block p-4 mb-8" style="max-width:480px;">
<div class="text-xs font-mono mb-3" style="color:rgba(255,255,255,0.2);">$ claude</div>
<div class="font-mono text-sm space-y-1">
<span class="terminal-line terminal-line-1" style="color:#FF9A04;">/ulk:bruce go</span>
<span class="terminal-line terminal-line-2" style="color:rgba(255,255,255,0.5);">scanning project...</span>
<span class="terminal-line terminal-line-3" style="color:#4ade80;">✓ ready — Next.js 14 detected</span>
</div>
</div>
<!-- CTA -->
<div class="flex flex-col sm:flex-row gap-3" style="max-width:480px;">
<div class="code-block flex items-center justify-between px-4 py-3 flex-1">
<code class="text-sm" style="color:#FF9A04;">
curl -fsSL …/install-remote.sh | bash
</code>
<button @click="copyInstall()"
class="ml-3 text-xs font-mono px-2 py-1 rounded transition-all flex-shrink-0"
style="background:rgba(255,154,4,0.15); color:#FF9A04; border:1px solid rgba(255,154,4,0.2);"
x-text="copied ? '✓ copied' : 'copy'">
</button>
</div>
<a href="https://github.com/izo/ulk" target="_blank"
class="text-sm font-mono px-4 py-3 rounded border transition-all text-center"
style="border-color:rgba(255,255,255,0.15); color:rgba(255,255,255,0.6);">
View source →
</a>
</div>
</div>
</section>
<!-- USE CASES -->
<section id="use-cases" style="background:#010230; padding:5rem 0;">
<div style="max-width:1100px; margin:0 auto; padding:0 2rem;">
<div class="section-header">
<span class="section-header-label">Use Cases</span>
<span style="font-size:11px; color:rgba(255,255,255,0.2); font-family:monospace;">10 workflows</span>
<span class="section-header-num">02 / 06</span>
</div>
<div class="space-y-0">
<template x-for="(uc, i) in useCases" :key="i">
<div class="use-case-row px-0 py-0" :class="{ 'open': uc.open }">
<!-- Row header -->
<button class="w-full text-left px-4 py-5 md:px-6 flex items-center gap-4 md:gap-8"
@click="uc.open = !uc.open">
<span class="font-mono font-black text-2xl md:text-4xl flex-shrink-0"
style="color:#FF9A04; width:3rem;" x-text="String(i+1).padStart(2,'0')"></span>
<span class="font-mono font-bold text-white text-sm md:text-base flex-1" x-text="uc.title"></span>
<span class="hidden md:flex items-center gap-2 text-xs font-mono flex-shrink-0"
style="color:rgba(255,255,255,0.35);">
<template x-for="(step, si) in uc.flow" :key="si">
<span class="flex items-center gap-1">
<span x-text="step"></span>
<span x-show="si < uc.flow.length - 1" style="color:rgba(255,154,4,0.4);">→</span>
</span>
</template>
</span>
<span class="font-mono text-xs px-2 py-1 rounded flex-shrink-0"
style="background:rgba(255,154,4,0.12); color:#FF9A04; border:1px solid rgba(255,154,4,0.2);"
x-text="uc.agent"></span>
<span class="font-mono text-xs ml-2 flex-shrink-0" style="color:rgba(255,154,4,0.5);"
x-text="uc.open ? '↑' : '↓'"></span>
</button>
<!-- Expanded content -->
<div x-show="uc.open" x-transition:enter="transition ease-out duration-200"
x-transition:enter-start="opacity-0 -translate-y-2"
x-transition:enter-end="opacity-100 translate-y-0"
class="px-4 md:px-6 pb-6 pt-0">
<div class="grid md:grid-cols-2 gap-6" style="border-top:1px solid rgba(255,154,4,0.1); padding-top:1.5rem;">
<div>
<div class="text-xs font-mono uppercase tracking-wider mb-3" style="color:#FF9A04;">Description</div>
<p class="text-sm font-sans" style="color:rgba(255,255,255,0.6); line-height:1.6;" x-text="uc.desc"></p>
</div>
<div>
<div class="text-xs font-mono uppercase tracking-wider mb-3" style="color:#FF9A04;">Commandes</div>
<div class="space-y-2">
<template x-for="cmd in uc.commands" :key="cmd">
<div class="code-block px-3 py-2 text-xs font-mono" style="color:#FF9A04;" x-text="cmd"></div>
</template>
</div>
</div>
</div>
</div>
</div>
</template>
</div>
</div>
</section>
<!-- AGENTS GRID -->
<section id="agents" style="background:#02065D; padding:5rem 0;">
<div style="max-width:1100px; margin:0 auto; padding:0 2rem;">
<div class="section-header">
<span class="section-header-label">Agents</span>
<span style="font-size:11px; color:rgba(255,255,255,0.2); font-family:monospace;"
x-text="filteredAgents.length + ' agents'"></span>
<span class="section-header-num">03 / 06</span>
</div>
<!-- Filters -->
<div class="flex flex-wrap gap-2 mb-8">
<template x-for="cat in categories" :key="cat.id">
<button class="filter-pill font-mono"
:class="{ 'active': activeCategory === cat.id }"
@click="activeCategory = cat.id"
x-text="cat.name"></button>
</template>
</div>
<!-- Grid -->
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3">
<template x-for="agent in filteredAgents" :key="agent.name">
<div class="agent-card p-4" @click="openModal(agent)">
<div class="flex items-start gap-3">
<div class="flex-shrink-0 w-8 h-8 rounded flex items-center justify-center"
style="background:rgba(255,154,4,0.1);">
<span class="iconify text-swiss" :data-icon="'mdi:' + (agent.icon || 'robot')"
style="width:16px;height:16px;"></span>
</div>
<div class="flex-1 min-w-0">
<div class="flex items-center gap-2 mb-1">
<span class="font-mono font-bold text-sm text-white" x-text="agent.name"></span>
<span class="text-xs font-mono px-1.5 py-0.5 rounded" x-show="agent.model === 'opus'"
style="background:rgba(255,154,4,0.12);color:#FF9A04;font-size:10px;">opus</span>
</div>
<p class="text-xs font-sans line-clamp-2" style="color:rgba(255,255,255,0.45);"
x-text="agent.description"></p>
</div>
</div>
<div class="mt-3 text-xs font-mono" style="color:rgba(255,154,4,0.5);">
<span x-text="'/ulk:' + agent.name"></span>
</div>
</div>
</template>
</div>
</div>
</section>
<!-- FEATURES -->
<section id="features" style="background:#010230; padding:5rem 0;">
<div style="max-width:1100px; margin:0 auto; padding:0 2rem;">
<div class="section-header">
<span class="section-header-label">Pourquoi ulk</span>
<span class="section-header-num">04 / 06</span>
</div>
<div class="grid md:grid-cols-3 gap-8">
<!-- Feature 1 -->
<div class="space-y-4">
<div class="flex gap-3 items-start">
<div class="swiss-circle flex-shrink-0" style="width:40px;height:40px;margin-top:4px;"></div>
<div>
<h3 class="font-mono font-black text-white text-lg mb-2">Zéro config</h3>
<p class="font-sans text-sm" style="color:rgba(255,255,255,0.5); line-height:1.6;">
Détection automatique de stack. Next.js, Nuxt, Astro, SPIP, Swift, Go, Python — aucun fichier à créer. Bruce détecte et orchestre.
</p>
</div>
</div>
</div>
<!-- Feature 2 -->
<div class="space-y-4">
<div class="flex gap-3 items-start">
<div style="width:40px;height:40px;background:#FF9A04;border-radius:4px;flex-shrink:0;margin-top:4px;
animation:pulse-slow 4s cubic-bezier(0.4,0,0.6,1) infinite 1s;"></div>
<div>
<h3 class="font-mono font-black text-white text-lg mb-2">Mémoire inter-sessions</h3>
<p class="font-sans text-sm" style="color:rgba(255,255,255,0.5); line-height:1.6;">
8 agents persistent leur état. Bruce se souvient du projet, de la stack, des préférences. Task Runner ajuste ses estimations.
</p>
</div>
</div>
</div>
<!-- Feature 3 -->
<div class="space-y-4">
<div class="flex gap-3 items-start">
<div style="width:40px;height:40px;flex-shrink:0;margin-top:4px;
border:3px solid #FF9A04;transform:rotate(45deg);
animation:spin 12s linear infinite;"></div>
<div>
<h3 class="font-mono font-black text-white text-lg mb-2">CLI > MCP</h3>
<p class="font-sans text-sm" style="color:rgba(255,255,255,0.5); line-height:1.6;">
Les outils CLI consomment 0 token. ulk utilise <code class="text-swiss">gh</code>, <code class="text-swiss">vercel</code>, <code class="text-swiss">neonctl</code> en priorité. MCP réservé à Figma, Notion, Linear.
</p>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- INSTALL -->
<section id="install" style="background:#000010; padding:5rem 0 6rem;">
<div style="max-width:700px; margin:0 auto; padding:0 2rem; text-align:center;">
<div class="font-mono font-black mb-2" style="font-size:clamp(2.5rem,8vw,5rem); color:#FF9A04; line-height:1;">
SHIP
</div>
<div class="font-mono font-black mb-10" style="font-size:clamp(2.5rem,8vw,5rem); color:rgba(255,255,255,0.15); line-height:1;">
TODAY.
</div>
<div class="code-block p-4 mb-4 text-left">
<div class="text-xs font-mono mb-2" style="color:rgba(255,255,255,0.2);">Installation</div>
<div class="flex items-center justify-between">
<code class="text-sm font-mono" style="color:#FF9A04;">
curl -fsSL https://raw.githubusercontent.com/izo/ulk/main/install-remote.sh | bash
</code>
<button @click="copyInstall()" class="ml-4 flex-shrink-0 text-xs font-mono px-3 py-1.5 rounded transition-all"
style="background:rgba(255,154,4,0.15); color:#FF9A04; border:1px solid rgba(255,154,4,0.2);"
x-text="copied ? '✓' : 'copy'"></button>
</div>
</div>
<div class="code-block p-4 mb-10 text-left text-xs font-mono space-y-1"
style="color:rgba(255,255,255,0.4);">
<div><span style="color:#FF9A04;">./install.sh</span> # base</div>
<div><span style="color:#FF9A04;">./install.sh</span> --with-vps # + 16 agents VPS</div>
<div><span style="color:#FF9A04;">./install.sh</span> --with-addy-skills # + checklists</div>
<div><span style="color:rgba(255,255,255,0.2);">./uninstall.sh</span> # désinstaller</div>
</div>
<div class="text-xs font-mono" style="color:rgba(255,255,255,0.2);">
MIT · <a href="https://github.com/izo/ulk" class="hover:text-swiss transition-colors">github.com/izo/ulk</a> · made with ulk
</div>
</div>
</section>
<!-- MODAL -->
<div class="modal-backdrop" x-show="modal.open" x-transition @click.self="modal.open = false"
style="display:none;">
<div class="modal-panel p-6">
<div class="flex items-center justify-between mb-4">
<span class="font-mono font-bold text-white text-lg" x-text="modal.agent?.name"></span>
<button @click="modal.open = false"
class="text-xs font-mono px-3 py-1 rounded"
style="background:rgba(255,255,255,0.05); color:rgba(255,255,255,0.5);">esc</button>
</div>
<div x-show="modal.loading" class="text-xs font-mono text-center py-8" style="color:#FF9A04;">
loading...
</div>
<div x-show="!modal.loading" class="font-sans text-sm" style="color:rgba(255,255,255,0.7); line-height:1.7;"
x-html="modal.content"></div>
</div>
</div>
<script>
function ulkApp() {
return {
copied: false,
activeCategory: 'all',
categories: [],
allAgents: [],
modal: { open: false, agent: null, content: '', loading: false },
useCases: [
{
open: false,
title: 'Nouveau projet',
flow: ['brief', 'spec', 'todo', 'ship'],
agent: 'bruce',
desc: 'Partez de zéro. Bruce interroge votre idée, Shuri génère la spec et le backlog Kanban, Task Runner exécute les premières tâches.',
commands: ['/ulk:bruce go', '/ulk:shuri mode=spec', '/ulk:task-runner']
},
{
open: false,
title: 'Session de développement',
flow: ['scan', 'tâche', 'commit', 'clear'],
agent: 'task-runner + 2b3',
desc: 'Godspeed scanne le projet en 30s, Task Runner prend la prochaine tâche, 2b3 checkpoint en fin de session.',
commands: ['/ulk:godspeed', '/ulk:bruce next', '/ulk:2b3']
},
{
open: false,
title: 'Audit pré-release',
flow: ['10 axes', 'score', 'GO/NO-GO'],
agent: 'sargeras',
desc: 'Audit omniscient sur 10 axes avec métriques quantitatives. Verdict production-ready avec liste des top 20 actions.',
commands: ['/ulk:sargeras', '/ulk:blackemperor', '# mode: audit-complet']
},
{
open: false,
title: 'Fixer des erreurs',
flow: ['erreur', 'diagnostic', 'patch'],
agent: 'robocop',
desc: 'Robocop détecte et corrige toutes les erreurs : runtime, compilation, tests, linting. Supporte tous les stacks.',
commands: ['/ulk:robocop', '/ulk:bruce fix', '# ou passer l\'issue GitHub']
},
{
open: false,
title: 'Documenter du code existant',
flow: ['code', 'spec', 'todo', 'sync'],
agent: 'strange',
desc: 'Strange reconstitue 6 documents depuis le code source (cahier des charges, doc technique, user stories, glossaire, architecture).',
commands: ['/ulk:strange', '/ulk:shuri mode=sync', '/ulk:friday mode=context']
},
{
open: false,
title: 'App mobile',
flow: ['web', 'API', 'iOS + Android'],
agent: 'happy → steve + fluke',
desc: 'Happy audite le projet web et génère l\'API complète (OpenAPI 3.1). Steve produit le starter SwiftUI, Fluke le starter Kotlin/Flutter.',
commands: ['/ulk:happy', '/ulk:steve', '/ulk:fluke']
},
{
open: false,
title: 'Migration de stack',
flow: ['source', 'plan', 'exécution'],
agent: 'ranma',
desc: 'Ranma planifie les migrations entre stacks : WordPress → SPIP, Next.js → Nuxt, PHP → Node, etc. Plan détaillé + exécution.',
commands: ['/ulk:ranma', '# ex: WordPress → Next.js']
},
{
open: false,
title: 'Déploiement',
flow: ['build', 'deploy', 'verify'],
agent: 'deploy:vercel',
desc: '5 agents de déploiement : Vercel, Netlify, Cloudflare, Docker, AWS. Détection automatique du framework, preview + production.',
commands: ['/ulk:deploy:vercel', '/ulk:deploy:docker', '/ulk:deploy:aws']
},
{
open: false,
title: 'Optimisation performance',
flow: ['CWV', 'bundle', 'DB', 'fix'],
agent: 'perf-auditor + vision',
desc: 'Perf Auditor mesure Core Web Vitals, bundle size et requêtes DB. Vision simplifie le code. Rapport avec priorités et fixes.',
commands: ['/ulk:perf-auditor', '/ulk:vision mode=simplify', '/ulk:blackemperor']
},
{
open: false,
title: 'Reverse design system',
flow: ['Figma', 'tokens', 'composants'],
agent: 'agamotto',
desc: 'Agamotto reconstitue le design system depuis Figma (MCP), Pencil ou Penpot : tokens, composants, patterns, guidelines → docs/design-system/.',
commands: ['/ulk:agamotto', '# nécessite Figma MCP ou fichier .pen']
},
],
get filteredAgents() {
if (this.activeCategory === 'all') return this.allAgents;
return this.allAgents.filter(a => a.category === this.activeCategory);
},
async init() {
try {
const res = await fetch('/data/commands.json');
const data = await res.json();
this.categories = [{ id: 'all', name: 'Tous' }, ...data.categories.map(c => ({ id: c.id, name: c.name }))];
this.allAgents = data.categories.flatMap(c =>
c.commands.map(cmd => ({ ...cmd, category: c.id, prefix: c.prefix }))
);
} catch(e) { console.warn('commands.json not loaded', e); }
},
copyInstall() {
navigator.clipboard.writeText('curl -fsSL https://raw.githubusercontent.com/izo/ulk/main/install-remote.sh | bash');
this.copied = true;
setTimeout(() => this.copied = false, 2000);
},
async openModal(agent) {
this.modal = { open: true, agent, content: '', loading: true };
try {
const agentFileMap = {
bruce: 'agents/orchestrators/25-bruce.md',
godspeed: 'agents/00-godspeed.md',
shuri: 'agents/docs/01-shuri.md',
'task-runner': 'agents/session/04-task-runner.md',
vision: 'agents/audit/05-vision.md',
'2b3': 'agents/session/08-2b3.md',
robocop: 'agents/session/11-robocop.md',
sargeras: 'agents/audit/45-sargeras.md',
gandalf: 'agents/session/34-gandalf.md',
};
const file = agentFileMap[agent.name] || `agents/${agent.name}.md`;
const url = `https://raw.githubusercontent.com/izo/ulk/main/${file}`;
const resp = await fetch(url);
if (resp.ok) {
const text = await resp.text();
this.modal.content = this.renderMarkdown(text.replace(/^---[\s\S]*?---\n/, '').slice(0, 3000));
} else {
this.modal.content = `<p style="color:#FF9A04">${agent.description}</p>`;
}
} catch(e) {
this.modal.content = `<p style="color:rgba(255,255,255,0.5)">${agent.description}</p>`;
}
this.modal.loading = false;
},
renderMarkdown(md) {
return md
.replace(/^#{1,3} (.+)$/gm, '<h3 style="color:#FF9A04;font-weight:700;margin:1em 0 0.5em;font-family:monospace;">$1</h3>')
.replace(/`([^`]+)`/g, '<code style="background:rgba(255,154,4,0.1);color:#FF9A04;padding:1px 4px;border-radius:3px;">$1</code>')
.replace(/\*\*([^*]+)\*\*/g, '<strong style="color:#fff;">$1</strong>')
.replace(/\n\n/g, '<br><br>')
.replace(/^- (.+)$/gm, '<li style="color:rgba(255,255,255,0.6);margin:4px 0;">$1</li>');
},
}
}
</script>
</body>
</html>
- Step 3 : Vérifier le fichier
wc -l /Users/izo/Dev/Docs/Ulk/site/index.html
Expected : environ 350-450 lignes.
- Step 4 : Ouvrir dans le navigateur
open /Users/izo/Dev/Docs/Ulk/site/index.html
Vérifier visuellement :
-
Fond navy #02065D
-
Nav sticky orange
-
Hero split : titre massif gauche + install droite
-
10 use cases listés (cliquables)
-
Grille agents (peut ne pas charger sans serveur)
-
Section features + install
-
Step 5 : Commit
cd /Users/izo/Dev/Docs/Ulk
git add site/index.html
git commit -m "feat(site): refonte Swiss Navy+Orange — hero split, 10 use cases, agents grid, Alpine.js"
Task 2 : Ajuster les chemins agents dans agentFileMap
Files:
- Modify:
site/index.html— sectionagentFileMapdans le script
La réorganisation des agents a changé les chemins. Mettre à jour le map avec les bons chemins post-réorganisation.
- Step 1 : Vérifier les chemins actuels des agents clés
ls /Users/izo/Dev/Docs/Ulk/agents/orchestrators/ | head -5
ls /Users/izo/Dev/Docs/Ulk/agents/session/ | head -10
ls /Users/izo/Dev/Docs/Ulk/agents/audit/ | head -10
ls /Users/izo/Dev/Docs/Ulk/agents/docs/ | head -5
- Step 2 : Mettre à jour agentFileMap dans site/index.html
Remplacer le bloc agentFileMap par un map complet avec les vrais chemins :
const agentFileMap = {
// Orchestrators
bruce: 'agents/orchestrators/25-bruce.md',
blackemperor: 'agents/orchestrators/18-blackemperor.md',
lovecraft: 'agents/orchestrators/47-obsidian-doc.md',
// Session
godspeed: 'agents/session/00-godspeed.md',
'task-runner': 'agents/session/04-task-runner.md',
'2b3': 'agents/session/08-2b3.md',
robocop: 'agents/session/11-robocop.md',
gandalf: 'agents/session/34-gandalf.md',
// Docs
shuri: 'agents/docs/01-shuri.md',
friday: 'agents/docs/09-friday.md',
strange: 'agents/docs/16-strange.md',
'obsidian-vault': 'agents/docs/39-obsidian-vault.md',
// Audit
vision: 'agents/audit/05-vision.md',
'a11y-auditor': 'agents/audit/06-a11y-auditor.md',
'perf-auditor': 'agents/audit/07-perf-auditor.md',
sargeras: 'agents/audit/45-sargeras.md',
'seo-auditor': 'agents/audit/32-seo-auditor.md',
amiral: 'agents/audit/41-amiral.md',
'claude-md-optimizer': 'agents/audit/42-claude-md-optimizer.md',
'tools-checker': 'agents/audit/43-tools-checker.md',
// Mobile
happy: 'agents/mobile/49-happy.md',
steve: 'agents/mobile/27-steve.md',
fluke: 'agents/mobile/48-fluke.md',
// Sync
bifrost: 'agents/sync/21-bifrost.md',
brigitte: 'agents/sync/24-brigitte.md',
// Specials
tony: 'agents/specials/50-tony.md',
rodin: 'agents/specials/46-rodin.md',
ranma: 'agents/specials/31-ranma.md',
picsou: 'agents/specials/26-picsou.md',
agamotto: 'agents/specials/17-agamotto.md',
sensei: 'agents/specials/38-sensei.md',
astride: 'agents/specials/40-astride.md',
};
NOTE : vérifier d’abord les vrais chemins avec ls agents/*/ avant d’appliquer. Corriger les chemins qui ne correspondent pas.
- Step 3 : Vérifier quelques chemins
ls /Users/izo/Dev/Docs/Ulk/agents/mobile/ 2>/dev/null || echo "mobile/ not found"
ls /Users/izo/Dev/Docs/Ulk/agents/specials/ 2>/dev/null || echo "specials/ not found"
ls /Users/izo/Dev/Docs/Ulk/agents/sync/ 2>/dev/null || echo "sync/ not found"
Adapter les chemins selon les dossiers réels qui existent.
- Step 4 : Commit
cd /Users/izo/Dev/Docs/Ulk
git add site/index.html
git commit -m "fix(site): mettre à jour agentFileMap avec chemins post-réorganisation"
Task 3 : Tester localement avec serveur HTTP
Files:
- Read:
site/index.html(test uniquement)
Le fichier doit tourner sur un serveur local (pas file://) pour que fetch('/data/commands.json') fonctionne.
- Step 1 : Lancer un serveur local
cd /Users/izo/Dev/Docs/Ulk/site
python3 -m http.server 8080
- Step 2 : Ouvrir dans le navigateur
Naviguer vers http://localhost:8080
Vérifier :
-
Nav sticky navy/orange visible
-
Hero : fond navy, titre “AI Dev ulk.”, cercles orange animés, terminal animation
-
Section Use Cases : 10 lignes numérotées, clic sur “01 Nouveau projet” expand/collapse
-
Section Agents : grille de cartes, filtres par catégorie fonctionnels (click “Agents”, “Deploy”, etc.)
-
Modal : clic sur une carte agent → modal s’ouvre, contenu markdown chargé
-
Section Features : 3 colonnes avec formes géométriques animées
-
Section Install : “SHIP TODAY.” + code block + copy button
-
Copy button : clic → texte change en ”✓”
-
Mobile : réduire fenêtre < 768px → layout stack vertical
-
Step 3 : Fixer les problèmes visuels
Si Alpine.js ne charge pas les agents (erreur CORS sur fetch local) : normal en file://, OK sur serveur.
Si les icônes Iconify ne s’affichent pas : vérifier la connexion internet (chargement CDN).
Si animations ne jouent pas : vérifier que le CSS animation est bien dans <style>.
- Step 4 : Commit final de polish
cd /Users/izo/Dev/Docs/Ulk
git add site/index.html
git commit -m "fix(site): polish post-test — ajustements visuels mineurs"
Task 4 : Vérification finale + .gitignore
- Step 1 : Ajouter .superpowers/ au .gitignore
echo ".superpowers/" >> /Users/izo/Dev/Docs/Ulk/.gitignore
- Step 2 : Vérifier le git status
cd /Users/izo/Dev/Docs/Ulk
git status
git log --oneline -5
- Step 3 : Vérifier que le déploiement GitHub Pages fonctionnera
# Vérifier que .nojekyll existe
ls /Users/izo/Dev/Docs/Ulk/site/.nojekyll
# Vérifier que data/commands.json est présent
ls /Users/izo/Dev/Docs/Ulk/site/data/commands.json
- Step 4 : Commit final
cd /Users/izo/Dev/Docs/Ulk
git add .gitignore
git commit -m "chore: add .superpowers/ to .gitignore"