Files
tunapro-garden/v2/index.html

308 lines
16 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="tr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>tunapro — gece bahçesi</title>
<meta name="description" content="Tuna Gül'ün dijital bahçesi, gece modu: projeler bir graf, notlar birer düğüm. tmux'ta yaşayan biri için doğal habitat.">
<style>
:root{
--bg:#0b0f0d; --panel:#10161200; --panel-solid:#101612; --line:#1e2b23;
--fg:#c9d6cc; --dim:#6d7f73; --green:#5dd39e; --amber:#e8b45a; --red:#e06c75;
--mono:ui-monospace,"JetBrains Mono","Fira Code",Menlo,Consolas,monospace;
}
*{box-sizing:border-box;margin:0;padding:0}
html,body{height:100%}
body{background:var(--bg);color:var(--fg);font-family:var(--mono);font-size:15px;line-height:1.6;overflow:hidden}
a{color:var(--green)}
#sky{position:fixed;inset:0;display:block;cursor:grab}
#sky.dragging{cursor:grabbing}
.hud{position:fixed;left:0;right:0;pointer-events:none;z-index:10}
.hud *{pointer-events:auto}
header.hud{top:0;padding:22px 26px;display:flex;justify-content:space-between;align-items:flex-start;gap:16px;flex-wrap:wrap}
.brand h1{font-size:18px;font-weight:600;color:var(--fg)}
.brand h1 .p{color:var(--green)}
.brand .sub{font-size:12.5px;color:var(--dim);max-width:52ch;margin-top:6px}
.legend{font-size:12px;color:var(--dim);text-align:right;line-height:1.9}
.legend .dot{display:inline-block;width:8px;height:8px;border-radius:50%;margin-right:6px;vertical-align:1px}
.legend .d1{background:var(--green)} .legend .d2{background:var(--amber)} .legend .d3{background:#7aa2f7}
footer.hud{bottom:0;background:var(--panel-solid);border-top:1px solid var(--line);
display:flex;align-items:center;gap:0;font-size:12.5px;height:34px;overflow:hidden}
footer .seg{padding:0 14px;display:flex;align-items:center;height:100%;white-space:nowrap}
footer .seg.g{background:var(--green);color:#08130d;font-weight:600}
footer .seg.dim{color:var(--dim)}
footer .grow{flex:1}
footer a{color:var(--fg);text-decoration:none;padding:0 10px;height:100%;display:flex;align-items:center}
footer a:hover{background:var(--line);color:var(--green)}
#card{
position:fixed;top:0;right:0;bottom:34px;width:min(460px,100vw);z-index:20;
background:rgba(13,19,15,.97);border-left:1px solid var(--line);
transform:translateX(105%);transition:transform .25s ease;
padding:28px;overflow-y:auto;backdrop-filter:blur(8px);
}
#card.open{transform:translateX(0)}
#card .close{position:absolute;top:16px;right:18px;background:none;border:1px solid var(--line);
color:var(--dim);font-family:var(--mono);font-size:13px;padding:3px 10px;cursor:pointer;border-radius:4px}
#card .close:hover{color:var(--red);border-color:var(--red)}
#card .stage{font-size:12px;color:var(--amber);letter-spacing:.08em;text-transform:uppercase}
#card h2{margin:10px 0 4px;font-size:22px;color:#fff}
#card .meta{font-size:12px;color:var(--dim);margin-bottom:16px}
#card .body{font-size:14px;color:var(--fg)}
#card .body p{margin-bottom:12px}
#card .body .cmt{color:var(--dim)}
#card .links{margin-top:18px;border-top:1px dashed var(--line);padding-top:14px;display:flex;flex-direction:column;gap:8px;font-size:13px}
#card .links a{text-decoration:none}
#card .links a:hover{text-decoration:underline}
#card .links a::before{content:"$ open ";color:var(--dim)}
#card .also{margin-top:18px;font-size:12.5px;color:var(--dim)}
#card .also button{background:var(--line);border:none;color:var(--green);font-family:var(--mono);
font-size:12px;padding:2px 8px;margin:2px 4px 2px 0;border-radius:3px;cursor:pointer}
#card .also button:hover{background:var(--green);color:#08130d}
#hint{position:fixed;left:50%;bottom:52px;transform:translateX(-50%);z-index:9;
font-size:12px;color:var(--dim);background:var(--panel-solid);border:1px solid var(--line);
padding:6px 14px;border-radius:20px;transition:opacity .5s}
#hint.hide{opacity:0}
@media(max-width:700px){.legend{display:none}}
@media (prefers-reduced-motion: reduce){ /* JS de yavaşlatır */ }
</style>
</head>
<body>
<canvas id="sky" aria-label="proje grafı: her yıldız bir not"></canvas>
<header class="hud">
<div class="brand">
<h1><span class="p">tuna@tunapro</span>:~/bahce $ <span style="color:var(--amber)">ls --graph</span></h1>
<div class="sub">Gece bahçesi. Her yıldız bir proje-notu, çizgiler fikirler arası kök bağlantıları.
Bir yıldıza tıkla; sürükleyip kurcalayabilirsin — bahçeler kurcalanmak içindir.</div>
</div>
<div class="legend">
<div><span class="dot d1"></span>🌳 köklendi — çalışıyor, yaşıyor</div>
<div><span class="dot d2"></span>🌿 büyüyor — düzenli commit alıyor</div>
<div><span class="dot d3"></span>🌱 fide — yarım fikir, taze toprak</div>
</div>
</header>
<div id="hint">bir yıldıza tıkla ✦</div>
<aside id="card" aria-live="polite">
<button class="close" onclick="closeCard()">esc</button>
<div class="stage" id="c-stage"></div>
<h2 id="c-title"></h2>
<div class="meta" id="c-meta"></div>
<div class="body" id="c-body"></div>
<div class="links" id="c-links"></div>
<div class="also" id="c-also"></div>
</aside>
<footer class="hud">
<span class="seg g">[bahce]</span>
<span class="seg">0:graf*</span>
<span class="seg dim">1:hakkımda</span>
<span class="grow"></span>
<a href="https://github.com/tunapro1234">github</a>
<a href="https://git.tunapro.xyz">gitea</a>
<a href="https://probotstudio.com">probot</a>
<a href="/yillik/">yıllık→</a>
<span class="seg dim" id="clock"></span>
<span class="seg dim">tunapro.xyz</span>
</footer>
<script>
const NOTES = {
ben: {
title:"tuna gül", stage:"çekirdek", tier:0, meta:"bahçıvan · mühendislik öğrencisi · TR",
body:`<p>Robotik, AI agent'lar, sistem mimarisi. İlkem: bir sistem <b>kurulabiliyorsa</b>, kurulacak — o yüzden izleyen değil kuran taraftayım.</p>
<p class="cmt"># bu graf benim kafamın içi; düğümler proje, kenarlar kök.</p>
<p>Her yerde <b>@tunapro1234</b>. Bu site dahil her şey kendi demirimde dönüyor.</p>`,
links:[["github.com/tunapro1234","https://github.com/tunapro1234"],["git.tunapro.xyz","https://git.tunapro.xyz"]],
edges:["blueprint","probot","homelab","frc","sims"]
},
blueprint: {
title:"blueprint (bp)", stage:"🌳 köklendi", tier:1, meta:"Go · tmux · dikim 2025, hâlâ sulanıyor",
body:`<p>tmux içinde bir AI agent <b>filosunu</b> yöneten orkestrasyon aracı. Paketler <code>BLUEPRINT.yaml</code> ile tanımlanır; snapshot tabanlı versiyonlama, symlink'le sabitlenen bağımlılıklar.</p>
<p class="cmt"># agent'lar tmux pane'lerinde yaşar. ben sadece bahçıvanım.</p>`,
links:[["bp.tunapro.xyz","https://bp.tunapro.xyz"],["github.com/tunapro1234/blueprint","https://github.com/tunapro1234/blueprint"]],
edges:["replicant","outpost","homelab"]
},
outpost: {
title:"outpost", stage:"🌿 büyüyor", tier:2, meta:"JavaScript · son push: bugün",
body:`<p>Graf-merkezli outreach aracı: insanlar, bağlantılar ve konuşmalar düğüm olarak tutulur. (Evet, bu sayfayla aynı fikir — grafları seviyorum.)</p>
<p>Canlı hali kilitli sera 🔒 — içinde gerçek insanlar var.</p>`,
links:[["github.com/tunapro1234/outpost","https://github.com/tunapro1234/outpost"],["outpost.tunapro.xyz (🔒)","https://outpost.tunapro.xyz"]],
edges:["metron"]
},
probot: {
title:"probot studio", stage:"🌳 köklendi", tier:1, meta:"C++ / Arduino · MIT · 9★",
body:`<p><i>«Bir kit, sonsuz robot.»</i> Arduino tabanlı robot yarışmaları için kütüphane + kit ekosistemi. Çekirdeği açık kaynak: <code>probot-core</code>, sahada denenmiş embedded control middleware.</p>`,
links:[["probotstudio.com","https://probotstudio.com"],["github.com/probot-studio/probot-core","https://github.com/probot-studio/probot-core"]],
edges:["frc"]
},
homelab: {
title:"homelab: *.tunapro.xyz", stage:"🌿 büyüyor", tier:2, meta:"7/24 vızıldıyor · self-host her şey",
body:`<p>Kod <a href="https://git.tunapro.xyz">Gitea</a>'da, medya kendi video sunucumda, Minecraft paneli <code>mcdash</code>'te, mail bile burada. Okuduğun sayfa da bu makinelerde.</p>
<p class="cmt"># bulut diye bir şey yok, başkasının bilgisayarı var.</p>`,
links:[["git.tunapro.xyz","https://git.tunapro.xyz"],["video.tunapro.xyz","https://video.tunapro.xyz"],["mcdash.tunapro.xyz","https://mcdash.tunapro.xyz"]],
edges:["blueprint"]
},
replicant: {
title:"replicant", stage:"🌱 fide", tier:3, meta:"Python · dikim may 2026",
body:`<p>Agent'ların kendini ve iş arkadaşlarını kopyalayıp çoğaltması üzerine deneyler. Adı tesadüf değil. Ne olacağını ben de bilmiyorum; fidelerin güzelliği bu.</p>`,
links:[["github.com/tunapro1234/replicant","https://github.com/tunapro1234/replicant"]],
edges:["metron","sims"]
},
metron: {
title:"metron", stage:"🌱 fide", tier:3, meta:"Python · 1★",
body:`<p>Ölçmediğin şeyi yönetemezsin: agent'lar ve sistemler için metrik/ölçüm katmanı. replicant koşar, metron sayar.</p>`,
links:[["github.com/tunapro1234/metron","https://github.com/tunapro1234/metron"]],
edges:[]
},
sims: {
title:"llm toplum simülasyonları", stage:"🌱 fide", tier:3, meta:"okuma listesi + deneyler",
body:`<p>AI agent'larla toplum kurma merakı: <b>hallucinating-splines</b>'ta agent'lar headless SimCity'de şehir kuruyor; <b>EDSL</b> ile AI destekli anket/deney tasarımı.</p>`,
links:[["awesome-llm-social-simulation","https://github.com/tunapro1234/awesome-llm-social-simulation"],["hallucinating-splines","https://github.com/tunapro1234/hallucinating-splines"]],
edges:["replicant"]
},
frc: {
title:"frc 7839 & 9029 → nfr", stage:"🌳 kökler", tier:1, meta:"robotiğe giriş kapım",
body:`<p>Robotikle FRC sahasında tanıştım (7839 ve 9029). O sahadan bir dönem donanım işine de girdik; benim payıma düşen kökler bugün Probot Studio'da yaşıyor.</p>`,
links:[["github.com/team-nf","https://github.com/team-nf"]],
edges:["probot"]
},
elevator: {
title:"elevator_optimization", stage:"🌱 fide", tier:3, meta:"Rust · 1★",
body:`<p>Asansör çizelgelemesi ne kadar optimize edilebilir? Rust'la yazılmış küçük bir saplantı. Beklerken düşünülen her şey proje olabilir.</p>`,
links:[["github.com/tunapro1234/elevator_optimization","https://github.com/tunapro1234/elevator_optimization"]],
edges:["ben"]
},
canbitirici: {
title:"can neden iş bitirici değil?", stage:"🍄 mantar", tier:4, meta:"hakemli değil ama kesin doğru",
body:`<p>Bahçenin gölgesinde kendiliğinden biten tür: titiz metodolojiyle(!) hazırlanmış araştırma raporu. Bilim kişisel, kindar ve grafikli olmalı.</p>`,
links:[["canbitirici.tunapro.xyz","https://canbitirici.tunapro.xyz"]],
edges:["ben"]
},
};
const COLORS = {0:"#ffffff",1:"#5dd39e",2:"#e8b45a",3:"#7aa2f7",4:"#e06c75"};
const RADII = {0:9,1:7,2:6,3:5,4:5};
const cv = document.getElementById("sky"), ctx = cv.getContext("2d");
let W,H,DPR; const nodes=[], edges=[];
const reduced = matchMedia("(prefers-reduced-motion: reduce)").matches;
function resize(){DPR=devicePixelRatio||1;W=innerWidth;H=innerHeight;cv.width=W*DPR;cv.height=H*DPR;cv.style.width=W+"px";cv.style.height=H+"px";ctx.setTransform(DPR,0,0,DPR,0,0);}
resize(); addEventListener("resize",resize);
const ids = Object.keys(NOTES);
ids.forEach((id,i)=>{
const a = (i/ids.length)*Math.PI*2;
const r = NOTES[id].tier===0?0:(120+NOTES[id].tier*60);
nodes.push({id,x:W/2+Math.cos(a)*r+(Math.random()*40-20),y:H/2+Math.sin(a)*r*0.7+(Math.random()*40-20),vx:0,vy:0,fixed:false});
});
ids.forEach(id=>NOTES[id].edges.forEach(t=>{ if(NOTES[t]) edges.push([id,t]); }));
const byId = id=>nodes.find(n=>n.id===id);
let selected=null, hover=null, drag=null, t=0;
function step(){
// hafif force layout
for(const n of nodes){
if(n.fixed||n===drag) continue;
let fx=0, fy=0;
for(const m of nodes){ if(m===n) continue;
const dx=n.x-m.x, dy=n.y-m.y, d2=dx*dx+dy*dy+0.01, d=Math.sqrt(d2);
const rep=Math.min(9000/d2,3); fx+=dx/d*rep; fy+=dy/d*rep;
}
for(const [a,b] of edges){
let o=null; if(a===n.id) o=byId(b); else if(b===n.id) o=byId(a);
if(!o) continue;
const dx=o.x-n.x, dy=o.y-n.y, d=Math.hypot(dx,dy)||1, pull=(d-140)*0.004;
fx+=dx/d*pull*d*0.02; fy+=dy/d*pull*d*0.02;
}
fx+=(W/2-n.x)*0.0012; fy+=(H/2-n.y)*0.0012;
n.vx=(n.vx+fx)*0.86; n.vy=(n.vy+fy)*0.86;
n.x+=n.vx; n.y+=n.vy;
n.x=Math.max(50,Math.min(W-50,n.x)); n.y=Math.max(90,Math.min(H-70,n.y));
}
}
function draw(){
t+=reduced?0:0.008;
ctx.clearRect(0,0,W,H);
// arka plan yıldız tozu
ctx.fillStyle="rgba(120,150,130,.25)";
for(let i=0;i<70;i++){
const x=(i*137.5)%W, y=(i*89.7)%H;
const tw=reduced?0.5:(Math.sin(t*2+i)*0.5+0.5);
ctx.globalAlpha=0.08+tw*0.12; ctx.fillRect(x,y,1.5,1.5);
}
ctx.globalAlpha=1;
// kenarlar
for(const [a,b] of edges){
const n1=byId(a), n2=byId(b);
const active = selected && (a===selected||b===selected);
ctx.strokeStyle = active? "rgba(93,211,158,.65)":"rgba(93,211,158,.14)";
ctx.lineWidth = active?1.6:1;
ctx.beginPath(); ctx.moveTo(n1.x,n1.y); ctx.lineTo(n2.x,n2.y); ctx.stroke();
}
// düğümler
for(const n of nodes){
const note=NOTES[n.id], r=RADII[note.tier], c=COLORS[note.tier];
const isSel=n.id===selected, isHov=n.id===hover;
const pulse = reduced?0:Math.sin(t*3+n.x)*1.2;
ctx.beginPath(); ctx.arc(n.x,n.y,r+(isSel?4:isHov?2:0)+ (note.tier===2?pulse*0.5:0),0,7);
ctx.fillStyle=c; ctx.shadowColor=c; ctx.shadowBlur=isSel||isHov?22:10; ctx.fill(); ctx.shadowBlur=0;
ctx.fillStyle = isSel||isHov ? "#e9f5ec" : "rgba(201,214,204,.75)";
ctx.font="12.5px ui-monospace,Menlo,monospace"; ctx.textAlign="center";
ctx.fillText(note.title, n.x, n.y+r+18);
}
step();
requestAnimationFrame(draw);
}
requestAnimationFrame(draw);
function pick(x,y){
for(const n of nodes){ if(Math.hypot(n.x-x,n.y-y)<22) return n; }
return null;
}
cv.addEventListener("pointermove",e=>{
if(drag){drag.x=e.clientX;drag.y=e.clientY;drag.vx=drag.vy=0;return;}
hover=pick(e.clientX,e.clientY)?.id||null;
cv.style.cursor=hover?"pointer":"grab";
});
let downAt=null;
cv.addEventListener("pointerdown",e=>{
const n=pick(e.clientX,e.clientY);
if(n){drag=n;cv.classList.add("dragging");downAt=[e.clientX,e.clientY];cv.setPointerCapture(e.pointerId);}
});
cv.addEventListener("pointerup",e=>{
cv.classList.remove("dragging");
if(drag&&downAt&&Math.hypot(e.clientX-downAt[0],e.clientY-downAt[1])<6) openCard(drag.id);
drag=null;downAt=null;
});
function openCard(id){
const n=NOTES[id]; selected=id;
document.getElementById("hint").classList.add("hide");
document.getElementById("c-stage").textContent=n.stage;
document.getElementById("c-title").textContent=n.title;
document.getElementById("c-meta").textContent=n.meta;
document.getElementById("c-body").innerHTML=n.body;
document.getElementById("c-links").innerHTML=n.links.map(([t,u])=>`<a href="${u}" target="_blank" rel="noopener">${t}</a>`).join("");
const also=n.edges.filter(e=>NOTES[e]);
document.getElementById("c-also").innerHTML = also.length?
"kökleri şuraya uzanıyor: "+also.map(e=>`<button onclick="openCard('${e}')">${NOTES[e].title}</button>`).join(""):"";
document.getElementById("card").classList.add("open");
}
function closeCard(){document.getElementById("card").classList.remove("open");selected=null;}
addEventListener("keydown",e=>{if(e.key==="Escape")closeCard();});
// tmux saati
const clock=document.getElementById("clock");
setInterval(()=>{const d=new Date();clock.textContent=d.toLocaleTimeString("tr-TR",{hour:"2-digit",minute:"2-digit"});},1000);
// açılışta merkezi ipucu
setTimeout(()=>{ if(!selected) openCard("ben"); }, 1400);
</script>
</body>
</html>