deniz bektaş

This commit is contained in:
2026-04-03 16:20:51 +03:00
parent d0cd1c7ee3
commit fb6933edd0
53 changed files with 4742 additions and 98 deletions

11
.claude/launch.json Normal file
View File

@@ -0,0 +1,11 @@
{
"version": "0.0.1",
"configurations": [
{
"name": "Next.js Dev Server",
"runtimeExecutable": "npm",
"runtimeArgs": ["run", "dev"],
"port": 3000
}
]
}

View File

@@ -1,7 +1,11 @@
{
"permissions": {
"allow": [
"Bash(npx create-next-app@latest . --typescript --tailwind --eslint --app --no-src-dir --import-alias \"@/*\" --yes)"
"Bash(npx create-next-app@latest . --typescript --tailwind --eslint --app --no-src-dir --import-alias \"@/*\" --yes)",
"Bash(npm install:*)",
"Bash(npm run:*)",
"mcp__Claude_Preview__preview_start",
"Bash(curl -s -o /dev/null -w \"%{http_code}\" http://localhost:3000)"
]
}
}

75
app/aktivite/page.tsx Normal file
View File

@@ -0,0 +1,75 @@
import type { Metadata } from "next";
import { getActivity } from "@/lib/activity";
import Link from "next/link";
export const metadata: Metadata = { title: "Aktivite" };
const typeIcons: Record<string, string> = {
post: "✍", notebook: "◎", infosec: "⚔", project: "◈",
link: "⊞", update: "▲", system: "⚙",
};
const typeLabels: Record<string, string> = {
post: "Blog", notebook: "Notebook", infosec: "Infosec",
project: "Proje", link: "Link", update: "Güncelleme", system: "Sistem",
};
export default function AktivitePage() {
const activities = getActivity();
return (
<div style={{ maxWidth: "100%" }}>
<div className="page-title">Aktivite</div>
<p style={{ fontSize: "0.8rem", color: "var(--text-muted)", marginBottom: "2rem" }}>
Sitede olan her şeyin kaydı changelog + activity stream
</p>
<div className="card">
<div style={{ fontFamily: "monospace", fontSize: "0.8rem" }}>
{activities.length === 0 ? (
<div style={{ color: "var(--text-muted)", fontStyle: "italic" }}>Henüz aktivite yok</div>
) : (
<ul style={{ listStyle: "none", display: "flex", flexDirection: "column" }}>
{activities.map((a) => (
<li
key={a.id}
style={{
display: "grid",
gridTemplateColumns: "140px 60px 1fr",
gap: "0.75rem",
alignItems: "flex-start",
padding: "0.6rem 0",
borderBottom: "1px solid var(--border)",
}}
>
<span style={{ color: "var(--text-muted)", fontSize: "0.7rem" }}>
{formatDateTime(a.timestamp)}
</span>
<span style={{ display: "flex", alignItems: "center", gap: "0.3rem", fontSize: "0.7rem" }}>
<span style={{ color: "var(--accent)" }}>{typeIcons[a.type] || "▶"}</span>
<span style={{ color: "var(--text-muted)" }}>{typeLabels[a.type] || a.type}</span>
</span>
<span>
{a.link ? (
<Link href={a.link} style={{ color: "var(--text)" }}>{a.message}</Link>
) : (
<span style={{ color: "var(--text)" }}>{a.message}</span>
)}
</span>
</li>
))}
</ul>
)}
</div>
</div>
</div>
);
}
function formatDateTime(iso: string) {
const d = new Date(iso);
return d.toLocaleString("tr-TR", {
year: "numeric", month: "2-digit", day: "2-digit",
hour: "2-digit", minute: "2-digit",
});
}

81
app/altyapi/page.tsx Normal file
View File

@@ -0,0 +1,81 @@
import type { Metadata } from "next";
export const metadata: Metadata = { title: "Altyapı" };
export default function AltyapiPage() {
return (
<div style={{ maxWidth: "100%" }}>
<div className="page-title">Altyapı</div>
<p style={{ fontSize: "0.8rem", color: "var(--text-muted)", marginBottom: "2rem" }}>
Bu sitenin nasıl çalıştığı
</p>
<div className="card prose" style={{ marginBottom: "1rem" }}>
<h2>Tech Stack</h2>
<ul>
<li><strong>Framework:</strong> Next.js 15 (App Router)</li>
<li><strong>Dil:</strong> TypeScript</li>
<li><strong>Stil:</strong> Tailwind CSS + custom CSS variables (tema sistemi)</li>
<li><strong>İçerik:</strong> Markdown dosyaları (gray-matter + remark)</li>
<li><strong>Font:</strong> JetBrains Mono (monospace her yerde)</li>
<li><strong>Tema:</strong> Dark/Light mode (localStorage tabanlı)</li>
</ul>
<h2>Hosting & Deployment</h2>
<ul>
<li><strong>Hosting:</strong> Vercel (free tier)</li>
<li><strong>Domain:</strong> denizbektas.com.tr</li>
<li><strong>CDN:</strong> Vercel Edge Network</li>
<li><strong>CI/CD:</strong> GitHub Vercel otomatik deploy</li>
<li><strong>SSL:</strong> Otomatik (Let&apos;s Encrypt via Vercel)</li>
</ul>
<h2>İçerik Yönetimi</h2>
<p>
CMS yok. Markdown dosyaları doğrudan. Yeni bir yazı eklemek için
<code>/content/blog/</code> klasörüne <code>.md</code> dosyası eklemek yeterli.
Git commit GitHub Vercel deploy 30 saniye.
</p>
<h2>RSS</h2>
<p>
RSS beslemeleri <code>/api/rss/*</code> route&apos;larından dinamik olarak üretiliyor.
Blog, infosec ve podcast için ayrı beslemeler mevcut.
</p>
<h2>Gizlilik</h2>
<ul>
<li>Analytics yok (Google Analytics, Plausible, vb.)</li>
<li>Cookie yok (tema tercihi hariç localStorage)</li>
<li>Üçüncü taraf script yok (font CDN hariç)</li>
<li>Log tutulmuyor (Vercel&apos;in standart logları hariç)</li>
</ul>
<h2>Kaynak Kodu</h2>
<p>
Bu sitenin kaynak kodu ık kaynak:{" "}
<a href="https://github.com/bugresearch/denizbektas.com.tr" target="_blank" rel="noopener noreferrer">
github.com/bugresearch/denizbektas.com.tr
</a>
</p>
<h2>Performans Hedefleri</h2>
<ul>
<li>Lighthouse Score: 95+</li>
<li>First Contentful Paint: &lt;1s</li>
<li>JavaScript: Minimum (sadece tema toggle)</li>
<li>Sayfa boyutu: &lt;100KB (font hariç)</li>
</ul>
<h2>Tasarım Felsefesi</h2>
<p>
Terminal estetik. Monospace font her yerde. Minimal JavaScript.
İçerik odaklı. Hızlı. Okunabilir.
</p>
<blockquote>
&quot;The best interface is no interface.&quot; Golden Krishna
</blockquote>
</div>
</div>
);
}

42
app/api/rss/all/route.ts Normal file
View File

@@ -0,0 +1,42 @@
import { NextResponse } from "next/server";
import { getAllPosts } from "@/lib/posts";
const SITE_URL = "https://denizbektas.com.tr";
export async function GET() {
const posts = getAllPosts();
const items = posts
.map(
(post) => `
<item>
<title><![CDATA[${post.title}]]></title>
<link>${SITE_URL}/${post.category}/${post.slug}</link>
<guid>${SITE_URL}/${post.category}/${post.slug}</guid>
<pubDate>${new Date(post.date).toUTCString()}</pubDate>
<description><![CDATA[${post.excerpt}]]></description>
<category>${post.category}</category>
</item>`
)
.join("\n");
const xml = `<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Deniz Bektaş — Tüm İçerikler</title>
<link>${SITE_URL}</link>
<description>Siber güvenlik, red team ve kişisel yazılar</description>
<language>tr</language>
<atom:link href="${SITE_URL}/api/rss/all" rel="self" type="application/rss+xml"/>
<lastBuildDate>${new Date().toUTCString()}</lastBuildDate>
${items}
</channel>
</rss>`;
return new NextResponse(xml, {
headers: {
"Content-Type": "application/xml; charset=utf-8",
"Cache-Control": "public, max-age=3600",
},
});
}

38
app/api/rss/blog/route.ts Normal file
View File

@@ -0,0 +1,38 @@
import { NextResponse } from "next/server";
import { getPosts } from "@/lib/posts";
const SITE_URL = "https://denizbektas.com.tr";
export async function GET() {
const posts = getPosts("blog");
const items = posts
.map(
(post) => `
<item>
<title><![CDATA[${post.title}]]></title>
<link>${SITE_URL}/blog/${post.slug}</link>
<guid>${SITE_URL}/blog/${post.slug}</guid>
<pubDate>${new Date(post.date).toUTCString()}</pubDate>
<description><![CDATA[${post.excerpt}]]></description>
</item>`
)
.join("\n");
const xml = `<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Deniz Bektaş — Kişisel Blog</title>
<link>${SITE_URL}/blog</link>
<description>Kişisel blog yazıları</description>
<language>tr</language>
<atom:link href="${SITE_URL}/api/rss/blog" rel="self" type="application/rss+xml"/>
<lastBuildDate>${new Date().toUTCString()}</lastBuildDate>
${items}
</channel>
</rss>`;
return new NextResponse(xml, {
headers: { "Content-Type": "application/xml; charset=utf-8", "Cache-Control": "public, max-age=3600" },
});
}

View File

@@ -0,0 +1,38 @@
import { NextResponse } from "next/server";
import { getPosts } from "@/lib/posts";
const SITE_URL = "https://denizbektas.com.tr";
export async function GET() {
const posts = getPosts("infosec");
const items = posts
.map(
(post) => `
<item>
<title><![CDATA[${post.title}]]></title>
<link>${SITE_URL}/infosec/${post.slug}</link>
<guid>${SITE_URL}/infosec/${post.slug}</guid>
<pubDate>${new Date(post.date).toUTCString()}</pubDate>
<description><![CDATA[${post.excerpt}]]></description>
</item>`
)
.join("\n");
const xml = `<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Deniz Bektaş — Infosec Posts</title>
<link>${SITE_URL}/infosec</link>
<description>Teknik siber güvenlik yazıları</description>
<language>tr</language>
<atom:link href="${SITE_URL}/api/rss/infosec" rel="self" type="application/rss+xml"/>
<lastBuildDate>${new Date().toUTCString()}</lastBuildDate>
${items}
</channel>
</rss>`;
return new NextResponse(xml, {
headers: { "Content-Type": "application/xml; charset=utf-8", "Cache-Control": "public, max-age=3600" },
});
}

View File

@@ -0,0 +1,23 @@
import { NextResponse } from "next/server";
const SITE_URL = "https://denizbektas.com.tr";
export async function GET() {
const xml = `<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Deniz Bektaş Podcast</title>
<link>${SITE_URL}/podcast</link>
<description>Türkçe siber güvenlik podcast&apos;i — red team, pentest ve hacker kültürü</description>
<language>tr</language>
<itunes:author>denizbektas</itunes:author>
<itunes:category text="Technology"/>
<atom:link href="${SITE_URL}/api/rss/podcast" rel="self" type="application/rss+xml"/>
<lastBuildDate>${new Date().toUTCString()}</lastBuildDate>
</channel>
</rss>`;
return new NextResponse(xml, {
headers: { "Content-Type": "application/xml; charset=utf-8", "Cache-Control": "public, max-age=3600" },
});
}

47
app/blog/[slug]/page.tsx Normal file
View File

@@ -0,0 +1,47 @@
import type { Metadata } from "next";
import Link from "next/link";
import { getPost, getPosts } from "@/lib/posts";
import { notFound } from "next/navigation";
export async function generateStaticParams() {
return getPosts("blog").map((p) => ({ slug: p.slug }));
}
export async function generateMetadata({ params }: { params: Promise<{ slug: string }> }): Promise<Metadata> {
const { slug } = await params;
const post = await getPost("blog", slug);
if (!post) return {};
return { title: post.title, description: post.excerpt };
}
export default async function BlogPostPage({ params }: { params: Promise<{ slug: string }> }) {
const { slug } = await params;
const post = await getPost("blog", slug);
if (!post) notFound();
return (
<div style={{ maxWidth: "100%" }}>
<Link href="/blog" style={{ fontSize: "0.78rem", color: "var(--text-muted)", display: "flex", alignItems: "center", gap: "0.3rem", marginBottom: "1.5rem" }}>
Blog&apos;a Dön
</Link>
<article>
<header style={{ marginBottom: "2rem" }}>
<h1 style={{ fontSize: "1.5rem", fontWeight: 800, color: "var(--text)", marginBottom: "0.5rem", lineHeight: 1.3 }}>
{post.title}
</h1>
<div style={{ display: "flex", alignItems: "center", gap: "1rem", flexWrap: "wrap" }}>
<span style={{ fontSize: "0.75rem", color: "var(--text-muted)" }}>
{new Date(post.date).toLocaleDateString("tr-TR", { year: "numeric", month: "long", day: "numeric" })}
</span>
<div style={{ display: "flex", gap: "0.3rem", flexWrap: "wrap" }}>
{post.tags.map((t) => <span key={t} className="tag">{t}</span>)}
</div>
</div>
</header>
<div className="card prose" dangerouslySetInnerHTML={{ __html: post.content || "" }} />
</article>
</div>
);
}

47
app/blog/page.tsx Normal file
View File

@@ -0,0 +1,47 @@
import type { Metadata } from "next";
import Link from "next/link";
import { getPosts } from "@/lib/posts";
export const metadata: Metadata = { title: "Personal Blog" };
export default function BlogPage() {
const posts = getPosts("blog");
return (
<div style={{ maxWidth: "100%" }}>
<div className="page-title">Personal Blog</div>
<p style={{ fontSize: "0.8rem", color: "var(--text-muted)", marginBottom: "2rem" }}>
Kişisel yazılar, düşünceler, kariyer notları
</p>
{posts.length === 0 ? (
<div className="card" style={{ color: "var(--text-muted)", fontSize: "0.85rem" }}>
Henüz yazı yok. Yakında...
</div>
) : (
<div style={{ display: "flex", flexDirection: "column", gap: "1rem" }}>
{posts.map((post) => (
<article key={post.slug} className="card">
<Link href={`/blog/${post.slug}`}>
<h2 style={{ fontSize: "1rem", fontWeight: 700, color: "var(--text)", marginBottom: "0.4rem", lineHeight: 1.4 }}>
{post.title}
</h2>
</Link>
<p style={{ fontSize: "0.82rem", color: "var(--text-muted)", marginBottom: "0.75rem", lineHeight: 1.6 }}>
{post.excerpt}
</p>
<div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", flexWrap: "wrap", gap: "0.5rem" }}>
<div style={{ display: "flex", gap: "0.3rem", flexWrap: "wrap" }}>
{post.tags.map((t) => <span key={t} className="tag">{t}</span>)}
</div>
<span style={{ fontSize: "0.72rem", color: "var(--text-muted)" }}>
{new Date(post.date).toLocaleDateString("tr-TR", { year: "numeric", month: "long", day: "numeric" })}
</span>
</div>
</article>
))}
</div>
)}
</div>
);
}

5
app/email/page.tsx Normal file
View File

@@ -0,0 +1,5 @@
import { redirect } from "next/navigation";
export default function EmailPage() {
redirect("mailto:info@denizbektas.com.tr");
}

View File

@@ -0,0 +1,122 @@
import type { Metadata } from "next";
export const metadata: Metadata = { title: "Faydalı Linkler" };
interface LinkItem {
title: string;
url: string;
description: string;
}
interface Category {
name: string;
icon: string;
links: LinkItem[];
}
const categories: Category[] = [
{
name: "Öğrenme Platformları",
icon: "◈",
links: [
{ title: "HackTheBox", url: "https://hackthebox.com", description: "CTF ve penetrasyon testi platformu" },
{ title: "TryHackMe", url: "https://tryhackme.com", description: "Yeni başlayanlar için siber güvenlik eğitimi" },
{ title: "PentesterLab", url: "https://pentesterlab.com", description: "Web güvenliği odaklı pratik eğitim" },
{ title: "PortSwigger Web Academy", url: "https://portswigger.net/web-security", description: "Burp Suite ekibinin ücretsiz web güvenlik eğitimi" },
{ title: "PicoCTF", url: "https://picoctf.org", description: "Carnegie Mellon üniversitesinin ücretsiz CTF platformu" },
],
},
{
name: "Araçlar",
icon: "⊡",
links: [
{ title: "Nmap", url: "https://nmap.org", description: "Ağ keşif ve güvenlik tarama aracı" },
{ title: "Burp Suite", url: "https://portswigger.net/burp", description: "Web uygulama güvenlik testi aracı" },
{ title: "Metasploit", url: "https://metasploit.com", description: "Penetrasyon testi framework'ü" },
{ title: "Ghidra", url: "https://ghidra-sre.org", description: "NSA'nın açık kaynak reverse engineering aracı" },
{ title: "CyberChef", url: "https://gchq.github.io/CyberChef", description: "Veri dönüştürme ve analiz aracı" },
{ title: "OSINT Framework", url: "https://osintframework.com", description: "OSINT araçları haritası" },
],
},
{
name: "Kaynaklar & Dokümantasyon",
icon: "▤",
links: [
{ title: "OWASP", url: "https://owasp.org", description: "Web güvenlik standartları ve kaynakları" },
{ title: "GTFOBins", url: "https://gtfobins.github.io", description: "Linux privilege escalation teknikleri" },
{ title: "LOLBAS", url: "https://lolbas-project.github.io", description: "Windows living off the land binaries" },
{ title: "PayloadsAllTheThings", url: "https://github.com/swisskyrepo/PayloadsAllTheThings", description: "Güvenlik testleri için payload koleksiyonu" },
{ title: "HackTricks", url: "https://book.hacktricks.xyz", description: "Kapsamlı hacking teknikleri kitabı" },
{ title: "Exploit Database", url: "https://exploit-db.com", description: "Public exploit veritabanı" },
],
},
{
name: "Red Team",
icon: "⚔",
links: [
{ title: "Red Team Notes", url: "https://www.ired.team", description: "Red team teknikleri ve notları" },
{ title: "Cobalt Strike Guide", url: "https://hstechdocs.helpsystems.com/manuals/cobaltstrike", description: "Cobalt Strike resmi dokümantasyonu" },
{ title: "BloodHound", url: "https://github.com/BloodHoundAD/BloodHound", description: "Active Directory saldırı yolları analizi" },
{ title: "Impacket", url: "https://github.com/impacket/impacket", description: "Python ağ protokol kütüphanesi" },
],
},
{
name: "Haberler & Blog",
icon: "◎",
links: [
{ title: "Krebs on Security", url: "https://krebsonsecurity.com", description: "Brian Krebs'in güvenlik blogu" },
{ title: "The Hacker News", url: "https://thehackernews.com", description: "Siber güvenlik haberleri" },
{ title: "Darknet Diaries", url: "https://darknetdiaries.com", description: "Gerçek siber suç hikayeleri podcast'i" },
{ title: "Project Zero Blog", url: "https://googleprojectzero.blogspot.com", description: "Google'ın güvenlik araştırma blogu" },
],
},
{
name: "CTF Writeupları",
icon: "◆",
links: [
{ title: "0xdf hacks stuff", url: "https://0xdf.gitlab.io", description: "HTB ve CTF writeupları" },
{ title: "IppSec YouTube", url: "https://www.youtube.com/@ippsec", description: "HTB makineleri video çözümleri" },
{ title: "CTFtime", url: "https://ctftime.org", description: "CTF yarışmaları takvimi ve arşivi" },
],
},
];
export default function FaydalıLinklerPage() {
return (
<div style={{ maxWidth: "100%" }}>
<div className="page-title">Faydalı Linkler</div>
<p style={{ fontSize: "0.8rem", color: "var(--text-muted)", marginBottom: "2rem" }}>
Kategorilere göre düzenlenmiş faydalı bağlantılar koleksiyonu
</p>
<div style={{ display: "flex", flexDirection: "column", gap: "1.5rem" }}>
{categories.map((cat) => (
<div key={cat.name}>
<div className="section-header">
<span style={{ color: "var(--accent)", marginRight: "0.4rem" }}>{cat.icon}</span>
{cat.name}
</div>
<div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(280px, 1fr))", gap: "0.5rem" }}>
{cat.links.map((link) => (
<a
key={link.url}
href={link.url}
target="_blank"
rel="noopener noreferrer"
className="card"
style={{ display: "block", textDecoration: "none", opacity: 1 }}
>
<div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: "0.25rem" }}>
<span style={{ fontSize: "0.85rem", fontWeight: 600, color: "var(--accent)" }}>{link.title}</span>
<span style={{ fontSize: "0.6rem", color: "var(--text-muted)" }}></span>
</div>
<p style={{ fontSize: "0.75rem", color: "var(--text-muted)", lineHeight: 1.5, margin: 0 }}>{link.description}</p>
</a>
))}
</div>
</div>
))}
</div>
</div>
);
}

71
app/fikirlerim/page.tsx Normal file
View File

@@ -0,0 +1,71 @@
import type { Metadata } from "next";
export const metadata: Metadata = { title: "Fikirlerim" };
interface Idea {
title: string;
body: string;
tags: string[];
date: string;
}
const ideas: Idea[] = [
{
title: "Güvenlik ve Gizlilik Aynı Şey Değil",
body: "İnsanlar genellikle güvenlik ile gizliliği karıştırıyor. Güvenli bir sistem sizi dış saldırılardan korur ama sizi izleyebilir. Gizlilik odaklı bir sistem ise sizi izlemez ama saldırılara karşı zayıf olabilir. İkisini birlikte sağlamak hem teknik hem felsefi bir meydan okuma.",
tags: ["güvenlik", "gizlilik", "felsefe"],
date: "2026-03-15",
},
{
title: "İnternet Hafızayı Yok Ediyor mu, Güçlendiriyor mu?",
body: "Her şeyi Google'a sormak beynimizi tembelleştiriyor deniyor. Ama belki de asıl sorunu çözdük: hafıza dışarıda depolanıyor, beyin daha üst düzey düşünmeye odaklanıyor. Problemi, hangi bilginin nerede arandığını bilmek.",
tags: ["bilişsel", "internet", "düşünce"],
date: "2026-02-20",
},
{
title: "Saldırgan Zihniyeti Savunmayı Güçlendirir",
body: "Red team'in asıl değeri sadece açık bulmak değil, savunma ekibinin göremediği şeyleri görünür kılmak. Bir sistemi kırmayı bilmek, onu korumanın en etkili yolu.",
tags: ["red team", "savunma", "siber güvenlik"],
date: "2026-01-10",
},
{
title: "Karmaşıklık = Saldırı Yüzeyi",
body: "Bir sistemdeki her özellik bir saldırı vektörüdür. En güvenli sistem en az özelliği olan sistemdir. Yazılım minimalizmi sadece estetik değil, güvenlik gerekliliği.",
tags: ["güvenlik", "tasarım", "minimalizm"],
date: "2025-12-01",
},
{
title: "Açık Kaynak = Güven mi?",
body: "Açık kaynak kod herkes tarafından incelenebilir ama herkes incelemiyor. Log4Shell açık kaynak bir kütüphanede yıllarca gizliydi. Şeffaflık gerekli ama yeterli değil. Güven, aktif inceleme gerektirir.",
tags: ["açık kaynak", "güven", "güvenlik"],
date: "2025-11-15",
},
];
export default function FikirlerimPage() {
return (
<div style={{ maxWidth: "100%" }}>
<div className="page-title">Fikirlerim</div>
<p style={{ fontSize: "0.8rem", color: "var(--text-muted)", marginBottom: "2rem" }}>
Düşündüğüm felsefi ve mantıksal şeyler kısa düşünceler, hipotezler
</p>
<div style={{ display: "flex", flexDirection: "column", gap: "1rem" }}>
{ideas.map((idea) => (
<div key={idea.title} className="card" style={{ borderLeft: "3px solid var(--accent-secondary)" }}>
<h2 style={{ fontSize: "0.95rem", fontWeight: 700, color: "var(--text)", marginBottom: "0.5rem" }}>{idea.title}</h2>
<p style={{ fontSize: "0.82rem", color: "var(--text-muted)", lineHeight: 1.7, marginBottom: "0.75rem" }}>{idea.body}</p>
<div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", flexWrap: "wrap", gap: "0.5rem" }}>
<div style={{ display: "flex", gap: "0.3rem", flexWrap: "wrap" }}>
{idea.tags.map((t) => <span key={t} className="tag">{t}</span>)}
</div>
<span style={{ fontSize: "0.7rem", color: "var(--text-muted)" }}>
{new Date(idea.date).toLocaleDateString("tr-TR", { year: "numeric", month: "long" })}
</span>
</div>
</div>
))}
</div>
</div>
);
}

57
app/gizlilik/page.tsx Normal file
View File

@@ -0,0 +1,57 @@
import type { Metadata } from "next";
export const metadata: Metadata = { title: "Gizlilik Politikası" };
export default function GizlilikPage() {
return (
<div style={{ maxWidth: "100%" }}>
<div className="page-title">Gizlilik Politikası</div>
<p style={{ fontSize: "0.8rem", color: "var(--text-muted)", marginBottom: "2rem" }}>
Son güncelleme: 3 Nisan 2026
</p>
<div className="card prose">
<h2>Kısa Versiyon</h2>
<p>
<strong>Hiçbir şey toplamıyoruz.</strong> Analytics yok, cookie yok, izleme yok.
</p>
<h2>Topladığımız Veriler</h2>
<p>
denizbektas.com.tr hiçbir kişisel veri toplamamaktadır. Özellikle:
</p>
<ul>
<li>Google Analytics veya benzeri analitik araç kullanılmamaktadır</li>
<li>Reklam ağları bulunmamaktadır</li>
<li>Oturum çerezi (session cookie) kullanılmamaktadır</li>
<li>E-posta adresi toplanmamaktadır</li>
<li>IP adresleri loglanmamaktadır (hosting sağlayıcısı olan Vercel&apos;in standart logları hariç)</li>
</ul>
<h2>Yerel Depolama</h2>
<p>
Yalnızca tema tercihiniz (dark/light) <code>localStorage</code> üzerinde yerel olarak
saklanmaktadır. Bu veri sunucuya gönderilmez.
</p>
<h2>Üçüncü Taraflar</h2>
<p>
Site JetBrains Mono fontunu bir CDN üzerinden yüklemektedir. Bu bağlantı sırasında
CDN sağlayıcısı IP adresinizi görebilir.
</p>
<h2>Hosting</h2>
<p>
Site Vercel altyapısında barındırılmaktadır. Vercel&apos;in kendi gizlilik politikası
geçerlidir.
</p>
<h2>İletişim</h2>
<p>
Gizlilik ile ilgili sorularınız için:{" "}
<a href="mailto:info@denizbektas.com.tr">info@denizbektas.com.tr</a>
</p>
</div>
</div>
);
}

View File

@@ -1,26 +1,166 @@
@import "tailwindcss";
:root {
--background: #ffffff;
--foreground: #171717;
--bg: #f5f5f0;
--bg-card: #ffffff;
--bg-hover: #f0f0ea;
--border: #d4d4c8;
--text: #1a1a1a;
--text-muted: #6b6b6b;
--accent: #005f99;
--accent-glow: #0077bb;
--accent-secondary: #6b21a8;
--tag-bg: #e8f4fd;
--tag-text: #005f99;
--sidebar-bg: #fafaf5;
--header-bg: rgba(245, 245, 240, 0.95);
--scrollbar: #c8c8bc;
--code-bg: #1a1a2e;
--code-text: #00d4aa;
}
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--font-sans: var(--font-geist-sans);
--font-mono: var(--font-geist-mono);
[data-theme="dark"] {
--bg: #0a0e17;
--bg-card: #0f1520;
--bg-hover: #141c2a;
--border: #1e2d3d;
--text: #e2e8f0;
--text-muted: #64748b;
--accent: #00d4aa;
--accent-glow: #00ffcc;
--accent-secondary: #7c6af7;
--tag-bg: #0d2137;
--tag-text: #00d4aa;
--sidebar-bg: #080c14;
--header-bg: rgba(8, 12, 20, 0.95);
--scrollbar: #1e2d3d;
--code-bg: #0d1117;
--code-text: #00d4aa;
}
@media (prefers-color-scheme: dark) {
:root {
--background: #0a0a0a;
--foreground: #ededed;
}
* { box-sizing: border-box; margin: 0; padding: 0; }
html {
font-size: 17px;
font-family: 'JetBrains Mono', 'Fira Code', 'Cascadia Code', 'Consolas', monospace;
background: var(--bg);
color: var(--text);
transition: background 0.2s, color 0.2s;
scroll-behavior: smooth;
}
body {
background: var(--background);
color: var(--foreground);
font-family: Arial, Helvetica, sans-serif;
body { min-height: 100vh; background: var(--bg); }
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--scrollbar); border-radius: 3px; }
a { color: var(--accent); text-decoration: none; transition: opacity 0.15s; }
a:hover { opacity: 0.75; }
.card {
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: 6px;
padding: 1.25rem;
transition: border-color 0.2s, background 0.2s;
}
.card:hover { border-color: var(--accent); }
.tag {
display: inline-block;
background: var(--tag-bg);
color: var(--tag-text);
font-size: 0.65rem;
padding: 0.15rem 0.5rem;
border-radius: 3px;
font-weight: 700;
letter-spacing: 0.06em;
text-transform: uppercase;
}
.prose {
line-height: 1.8;
font-size: 0.9rem;
}
.prose h1, .prose h2, .prose h3, .prose h4 {
color: var(--text);
margin-top: 1.75rem;
margin-bottom: 0.75rem;
font-weight: 700;
}
.prose h1 { font-size: 1.5rem; border-bottom: 1px solid var(--border); padding-bottom: 0.5rem; }
.prose h2 { font-size: 1.15rem; color: var(--accent); }
.prose h3 { font-size: 1rem; }
.prose p { margin-bottom: 1rem; }
.prose ul, .prose ol { margin: 0.75rem 0 1rem 1.5rem; }
.prose li { margin-bottom: 0.3rem; }
.prose code {
background: var(--code-bg);
color: var(--code-text);
padding: 0.1rem 0.35rem;
border-radius: 3px;
font-size: 0.85em;
font-family: inherit;
}
.prose pre {
background: var(--code-bg);
color: var(--code-text);
padding: 1rem 1.25rem;
border-radius: 6px;
overflow-x: auto;
margin: 1rem 0;
border: 1px solid var(--border);
font-size: 0.82rem;
line-height: 1.6;
}
.prose pre code { background: none; padding: 0; }
.prose blockquote {
border-left: 3px solid var(--accent);
padding-left: 1rem;
color: var(--text-muted);
margin: 1rem 0;
}
.prose a { color: var(--accent); }
.prose strong { font-weight: 700; }
.prose hr { border: none; border-top: 1px solid var(--border); margin: 2rem 0; }
.prose table { width: 100%; border-collapse: collapse; margin: 1rem 0; font-size: 0.88rem; }
.prose th { background: var(--bg-card); border: 1px solid var(--border); padding: 0.5rem 0.75rem; text-align: left; color: var(--accent); }
.prose td { border: 1px solid var(--border); padding: 0.5rem 0.75rem; }
.page-title {
font-size: 1.4rem;
font-weight: 700;
color: var(--accent);
display: flex;
align-items: center;
gap: 0.4rem;
margin-bottom: 0.2rem;
}
.page-title::before { content: '//'; opacity: 0.35; font-weight: 400; }
.section-header {
font-size: 0.72rem;
font-weight: 700;
letter-spacing: 0.1em;
text-transform: uppercase;
color: var(--text-muted);
margin-bottom: 0.5rem;
padding-bottom: 0.35rem;
border-bottom: 1px solid var(--border);
}
.blink { animation: blink 1s step-end infinite; }
@keyframes blink { 50% { opacity: 0; } }
.terminal-line {
display: flex;
align-items: flex-start;
gap: 0.5rem;
font-size: 0.85rem;
padding: 0.3rem 0;
border-bottom: 1px solid var(--border);
color: var(--text-muted);
}
.terminal-line:last-child { border-bottom: none; }
.terminal-line .prompt { color: var(--accent); flex-shrink: 0; }

66
app/hakkimda/page.tsx Normal file
View File

@@ -0,0 +1,66 @@
import type { Metadata } from "next";
export const metadata: Metadata = { title: "Hakkımda" };
export default function HakkimdaPage() {
return (
<div style={{ maxWidth: "100%" }}>
<div className="page-title">Hakkımda</div>
<p style={{ fontSize: "0.8rem", color: "var(--text-muted)", marginBottom: "2rem" }}>
Kim olduğum hakkında kısa bilgi
</p>
<div className="card" style={{ marginBottom: "1rem" }}>
<div style={{ display: "flex", alignItems: "center", gap: "0.5rem", marginBottom: "1rem" }}>
<div style={{ width: "48px", height: "48px", background: "var(--bg)", border: "2px solid var(--accent)", borderRadius: "6px", display: "flex", alignItems: "center", justifyContent: "center", fontSize: "1.5rem" }}>
🦈
</div>
<div>
<div style={{ fontWeight: 700, fontSize: "0.95rem" }}>Deniz Bektaş</div>
<div style={{ fontSize: "0.75rem", color: "var(--text-muted)" }}>Siber Güvenlik Araştırmacısı</div>
</div>
</div>
<div className="prose">
<p>
Merhaba, ben Deniz Bektaş. Siber güvenlik alanında uzmanlaşmış, özellikle offensive security
ve red team operasyonlarına odaklanan bir araştırmacıyım.
</p>
<p>
Sistemlerin güvenlik ıklarını bulmak, istismar etmek ve raporlamak benim işim.
Ama daha önemlisi: bunları anlayarak daha güvenli sistemler inşa etmeye katkı sağlamak.
</p>
<h2>Uzmanlık Alanları</h2>
<ul>
<li>Red Team Operasyonları</li>
<li>Web Application Penetration Testing</li>
<li>Network Security Assessment</li>
<li>OSINT &amp; Reconnaissance</li>
<li>Malware Analysis (Statik/Dinamik)</li>
<li>CTF (Capture The Flag)</li>
</ul>
<h2>Sertifikalar &amp; Eğitim</h2>
<ul>
<li>OSCP (Hedef 2026)</li>
<li>eJPT eLearnSecurity</li>
<li>TryHackMe Top %1</li>
</ul>
<h2>Araçlar</h2>
<p>
Kali Linux, Burp Suite, Nmap, Metasploit, Cobalt Strike (lab), Ghidra, Wireshark...
Detaylar için{" "}
<a href="/takim-cantam">Takım Çantam</a> sayfasına bakabilirsin.
</p>
<h2>Dışında</h2>
<p>
Kod yazmak, kitap okumak, müzik dinlemek (darksynth, industrial), kafein tüketmek.
</p>
</div>
</div>
</div>
);
}

74
app/hobilerim/page.tsx Normal file
View File

@@ -0,0 +1,74 @@
import type { Metadata } from "next";
export const metadata: Metadata = { title: "Hobilerim" };
const hobbies = [
{
name: "CTF (Capture The Flag)",
icon: "◆",
desc: "CTF yarışmaları benim için hem öğrenme hem de eğlence. Kriptografi, binary exploitation, web, OSINT kategorilerinde oynuyorum.",
tags: ["pwn", "crypto", "web", "osint"],
},
{
name: "Müzik Dinleme",
icon: "◉",
desc: "Darksynth, industrial, dark ambient ve black metal. Çalışırken müzik şart.",
tags: ["darksynth", "industrial", "metal"],
},
{
name: "Kitap Okuma",
icon: "▤",
desc: "Teknik kitaplar, felsefe ve distopik roman. Son okuduğum: Neuromancer.",
tags: ["fiction", "philosophy", "technical"],
},
{
name: "Araç Geliştirme",
icon: "◈",
desc: "Açık kaynak güvenlik araçları geliştirmek. Python ve Rust ile kendi toollarımı yazıyorum.",
tags: ["python", "rust", "open-source"],
},
{
name: "Elektronik & Donanım",
icon: "⊡",
desc: "Flipper Zero, Raspberry Pi, Arduino ile oynamak. RF sinyalleri, protokol analizi.",
tags: ["hardware", "RF", "embedded"],
},
{
name: "Fotoğrafçılık",
icon: "◎",
desc: "Özellikle urban exploration ve siyah-beyaz fotoğrafçılık. Dijital değil, analog film.",
tags: ["film", "analog", "urbex"],
},
{
name: "Yürüyüş & Doğa",
icon: "◇",
desc: "Ekrandan uzaklaşmak için en iyi şey. Orman yürüyüşleri, mümkün olduğunda kamp.",
tags: ["hiking", "nature", "camping"],
},
];
export default function HobilerimPage() {
return (
<div style={{ maxWidth: "100%" }}>
<div className="page-title">Hobilerim</div>
<p style={{ fontSize: "0.8rem", color: "var(--text-muted)", marginBottom: "2rem" }}>
İş dışında neler yapıyorum
</p>
<div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(300px, 1fr))", gap: "0.75rem" }}>
{hobbies.map((h) => (
<div key={h.name} className="card">
<div style={{ display: "flex", alignItems: "center", gap: "0.5rem", marginBottom: "0.5rem" }}>
<span style={{ color: "var(--accent)", fontSize: "0.9rem" }}>{h.icon}</span>
<h3 style={{ fontSize: "0.9rem", fontWeight: 600, color: "var(--text)" }}>{h.name}</h3>
</div>
<p style={{ fontSize: "0.8rem", color: "var(--text-muted)", lineHeight: 1.6, marginBottom: "0.6rem" }}>{h.desc}</p>
<div style={{ display: "flex", gap: "0.3rem", flexWrap: "wrap" }}>
{h.tags.map((t) => <span key={t} className="tag">{t}</span>)}
</div>
</div>
))}
</div>
</div>
);
}

36
app/humans.txt/route.ts Normal file
View File

@@ -0,0 +1,36 @@
import { NextResponse } from "next/server";
export async function GET() {
const content = `/* TEAM */
Developer / Writer: Deniz Bektaş
Contact: info@denizbektas.com.tr
Mastodon: @denizbektas@mastadon.org
Location: Türkiye
/* THANKS */
Next.js team
Vercel
The open source community
Everyone who taught me something
/* SITE */
Last update: 2026/04/03
Language: Turkish / English
Doctype: HTML5
IDE: Neovim
Standards: CSS3, JavaScript ES2024
Components: React, Next.js
Software: Cachy OS, Parrot OS, macOS
/* FOR HUMANS */
This site was built by a human, for humans.
No AI-generated content. No dark patterns.
Just someone sharing their journey.
humanstxt.org
`;
return new NextResponse(content, {
headers: { "Content-Type": "text/plain; charset=utf-8" },
});
}

69
app/iletisim/page.tsx Normal file
View File

@@ -0,0 +1,69 @@
import type { Metadata } from "next";
export const metadata: Metadata = { title: "İletişim" };
const socials = [
{ name: "E-Mail", value: "info@denizbektas.com.tr", href: "mailto:info@denizbektas.com.tr", icon: "✉", desc: "Genel iletişim için" },
{ name: "Mastodon", value: "@denizbektas@infosec.exchange", href: "https://infosec.exchange/@denizbektas", icon: "⊕", desc: "Günlük paylaşımlar" },
{ name: "GitHub", value: "github.com/bugresearch", href: "https://github.com/bugresearch", icon: "◈", desc: "Açık kaynak projeler" },
{ name: "LinkedIn", value: "linkedin.com/in/denizbektas", href: "https://linkedin.com/in/denizbektas", icon: "▤", desc: "Profesyonel ağ" },
{ name: "PGP Key", value: "public.pgp", href: "/public.pgp", icon: "⊘", desc: "Şifreli iletişim için" },
];
export default function IletisimPage() {
return (
<div style={{ maxWidth: "100%" }}>
<div className="page-title">İletişim</div>
<p style={{ fontSize: "0.8rem", color: "var(--text-muted)", marginBottom: "2rem" }}>
Ulaşabileceğiniz kanallar iletişim formu yok, doğrudan iletişim var
</p>
<div style={{ display: "flex", flexDirection: "column", gap: "0.75rem", marginBottom: "2rem" }}>
{socials.map((s) => (
<a
key={s.name}
href={s.href}
target={s.href.startsWith("http") ? "_blank" : undefined}
rel={s.href.startsWith("http") ? "noopener noreferrer" : undefined}
className="card"
style={{ display: "flex", alignItems: "center", gap: "1rem", opacity: 1 }}
>
<div style={{ width: "36px", height: "36px", background: "var(--bg)", border: "1px solid var(--border)", borderRadius: "6px", display: "flex", alignItems: "center", justifyContent: "center", fontSize: "1rem", flexShrink: 0, color: "var(--accent)" }}>
{s.icon}
</div>
<div style={{ flex: 1 }}>
<div style={{ fontSize: "0.88rem", fontWeight: 600, color: "var(--text)" }}>{s.name}</div>
<div style={{ fontSize: "0.75rem", color: "var(--accent)", fontFamily: "monospace" }}>{s.value}</div>
<div style={{ fontSize: "0.72rem", color: "var(--text-muted)" }}>{s.desc}</div>
</div>
{s.href.startsWith("http") && <span style={{ color: "var(--text-muted)", fontSize: "0.7rem" }}></span>}
</a>
))}
</div>
<div className="card prose">
<h2>PGP ile Şifreli İletişim</h2>
<p>
Hassas konular için PGP ile şifrelenmiş mesaj gönderebilirsiniz.
Public key&apos;im <a href="/public.pgp">burada</a>.
</p>
<pre style={{ fontSize: "0.75rem", padding: "0.75rem" }}>
{`gpg --fetch-keys https://denizbektas.com.tr/public.pgp
gpg --encrypt -r info@denizbektas.com.tr mesaj.txt`}
</pre>
<h2>Ne Zaman Yanıt Veririm?</h2>
<p>
Genellikle 24-48 saat içinde yanıt veriyorum. Reklam, birliği teklifi veya
spam içerikli mesajlara yanıt vermiyorum.
</p>
<h2>Responsible Disclosure</h2>
<p>
Bir güvenlik ığı bildirmek istiyorsanız lütfen{" "}
<a href="/security.txt">/security.txt</a> dosyasını inceleyin.
</p>
</div>
</div>
);
}

View File

@@ -0,0 +1,54 @@
import type { Metadata } from "next";
import Link from "next/link";
import { getPost, getPosts } from "@/lib/posts";
import { notFound } from "next/navigation";
export async function generateStaticParams() {
return getPosts("infosec").map((p) => ({ slug: p.slug }));
}
export async function generateMetadata({ params }: { params: Promise<{ slug: string }> }): Promise<Metadata> {
const { slug } = await params;
const post = await getPost("infosec", slug);
if (!post) return {};
return { title: post.title, description: post.excerpt };
}
export default async function InfosecPostPage({ params }: { params: Promise<{ slug: string }> }) {
const { slug } = await params;
const post = await getPost("infosec", slug);
if (!post) notFound();
return (
<div style={{ maxWidth: "100%" }}>
<Link href="/infosec" style={{ fontSize: "0.78rem", color: "var(--text-muted)", display: "flex", alignItems: "center", gap: "0.3rem", marginBottom: "1.5rem" }}>
Infosec&apos;e Dön
</Link>
<article>
<header style={{ marginBottom: "2rem" }}>
<div style={{ display: "flex", alignItems: "center", gap: "0.5rem", marginBottom: "0.5rem" }}>
<span style={{ color: "var(--accent)", fontSize: "0.8rem" }}></span>
<span className="tag">infosec</span>
</div>
<h1 style={{ fontSize: "1.5rem", fontWeight: 800, color: "var(--text)", marginBottom: "0.5rem", lineHeight: 1.3 }}>
{post.title}
</h1>
<div style={{ display: "flex", alignItems: "center", gap: "1rem", flexWrap: "wrap" }}>
<span style={{ fontSize: "0.75rem", color: "var(--text-muted)" }}>
{new Date(post.date).toLocaleDateString("tr-TR", { year: "numeric", month: "long", day: "numeric" })}
</span>
<div style={{ display: "flex", gap: "0.3rem", flexWrap: "wrap" }}>
{post.tags.map((t) => <span key={t} className="tag">{t}</span>)}
</div>
</div>
<div style={{ marginTop: "0.75rem", padding: "0.6rem 0.75rem", background: "var(--bg)", border: "1px solid var(--border)", borderRadius: "4px", fontSize: "0.75rem", color: "var(--text-muted)" }}>
Bu içerik yalnızca eğitim amaçlıdır. Sadece yetkili sistemlerde test yapın.
</div>
</header>
<div className="card prose" dangerouslySetInnerHTML={{ __html: post.content || "" }} />
</article>
</div>
);
}

48
app/infosec/page.tsx Normal file
View File

@@ -0,0 +1,48 @@
import type { Metadata } from "next";
import Link from "next/link";
import { getPosts } from "@/lib/posts";
export const metadata: Metadata = { title: "Infosec Posts" };
export default function InfosecPage() {
const posts = getPosts("infosec");
return (
<div style={{ maxWidth: "100%" }}>
<div className="page-title">Infosec Posts</div>
<p style={{ fontSize: "0.8rem", color: "var(--text-muted)", marginBottom: "2rem" }}>
Teknik güvenlik yazıları, tool analizleri, CTF writeupları
</p>
{posts.length === 0 ? (
<div className="card" style={{ color: "var(--text-muted)", fontSize: "0.85rem" }}>Henüz yazı yok.</div>
) : (
<div style={{ display: "flex", flexDirection: "column", gap: "1rem" }}>
{posts.map((post) => (
<article key={post.slug} className="card">
<div style={{ display: "flex", alignItems: "center", gap: "0.5rem", marginBottom: "0.5rem" }}>
<span style={{ color: "var(--accent)", fontSize: "0.7rem" }}></span>
<Link href={`/infosec/${post.slug}`}>
<h2 style={{ fontSize: "1rem", fontWeight: 700, color: "var(--text)", lineHeight: 1.4 }}>
{post.title}
</h2>
</Link>
</div>
<p style={{ fontSize: "0.82rem", color: "var(--text-muted)", marginBottom: "0.75rem", lineHeight: 1.6 }}>
{post.excerpt}
</p>
<div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", flexWrap: "wrap", gap: "0.5rem" }}>
<div style={{ display: "flex", gap: "0.3rem", flexWrap: "wrap" }}>
{post.tags.map((t) => <span key={t} className="tag">{t}</span>)}
</div>
<span style={{ fontSize: "0.72rem", color: "var(--text-muted)" }}>
{new Date(post.date).toLocaleDateString("tr-TR", { year: "numeric", month: "long", day: "numeric" })}
</span>
</div>
</article>
))}
</div>
)}
</div>
);
}

View File

@@ -0,0 +1,60 @@
import type { Metadata } from "next";
export const metadata: Metadata = { title: "Kullanım Koşulları" };
export default function KullanimKosullariPage() {
return (
<div style={{ maxWidth: "100%" }}>
<div className="page-title">Kullanım Koşulları</div>
<p style={{ fontSize: "0.8rem", color: "var(--text-muted)", marginBottom: "2rem" }}>
Son güncelleme: 3 Nisan 2026
</p>
<div className="card prose">
<h2>İçerik Kullanımı</h2>
<p>
Bu sitedeki tüm içerikler <strong>CC BY-NC-SA 4.0</strong> lisansı altındadır.
Yani:
</p>
<ul>
<li>Atıf vererek paylaşabilirsiniz</li>
<li>Ticari amaçla kullanamazsınız</li>
<li>Değiştirdiğinizde aynı lisansla paylaşmalısınız</li>
</ul>
<h2>Teknik İçerik</h2>
<p>
Sitedeki teknik güvenlik içerikleri <strong>yalnızca eğitim amaçlıdır</strong>.
Bu bilgileri yetkisiz sistemlerde kullanmak yasadışıdır. Yazar, içeriklerin
kötüye kullanımından sorumlu tutulamaz.
</p>
<h2>Disclaimer</h2>
<p>
Bu sitedeki tüm görüşler yalnızca yazara aittir. Herhangi bir kuruluşu
temsil etmemektedir.
</p>
<p>
İçerikler &quot;olduğu gibi&quot; sunulmaktadır. Hata içerebilir. Doğrulamak
okuyucunun sorumluluğundadır.
</p>
<h2>Linkler</h2>
<p>
Dış bağlantıların içeriğinden sorumlu değilim. Bir bağlantı bir onay anlamına gelmez.
</p>
<h2>Değişiklikler</h2>
<p>
Bu koşullar herhangi bir bildirim yapılmaksızın değiştirilebilir.
Son güncelleme tarihini takip edin.
</p>
<h2>İletişim</h2>
<p>
<a href="mailto:info@denizbektas.com.tr">info@denizbektas.com.tr</a>
</p>
</div>
</div>
);
}

View File

@@ -1,33 +1,82 @@
import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import "./globals.css";
const geistSans = Geist({
variable: "--font-geist-sans",
subsets: ["latin"],
});
const geistMono = Geist_Mono({
variable: "--font-geist-mono",
subsets: ["latin"],
});
import { ThemeProvider } from "@/components/ThemeProvider";
import Navigation from "@/components/Navigation";
export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
title: {
default: "Deniz Bektaş | Application Security Engineer",
template: "%s | Deniz Bektaş",
},
description: "Siber güvenlik uzmanı, red teamer ve araştırmacı.",
keywords: ["deniz bektas", "siber güvenlik", "red team", "infosec", "penetration testing", "bugresearch"],
authors: [{ name: "Deniz Bektaş" }],
openGraph: {
type: "website",
locale: "tr_TR",
siteName: "denizbektas.com.tr",
},
};
export default function RootLayout({
children,
}: Readonly<{
}: {
children: React.ReactNode;
}>) {
}) {
return (
<html
lang="en"
className={`${geistSans.variable} ${geistMono.variable} h-full antialiased`}
>
<body className="min-h-full flex flex-col">{children}</body>
<html lang="tr" suppressHydrationWarning>
<head>
<link
rel="alternate"
type="application/rss+xml"
title="Deniz Bektaş - Tüm İçerikler"
href="/api/rss/all"
/>
<link
rel="alternate"
type="application/rss+xml"
title="Deniz Bektaş - Blog"
href="/api/rss/blog"
/>
<link
rel="alternate"
type="application/rss+xml"
title="Deniz Bektaş - Infosec"
href="/api/rss/infosec"
/>
</head>
<body suppressHydrationWarning>
<ThemeProvider>
<div
style={{
display: "flex",
minHeight: "100vh",
}}
>
<Navigation />
<main
style={{
flex: 1,
minWidth: 0,
padding: "2rem",
paddingTop: "2rem",
}}
className="main-content"
>
{children}
</main>
</div>
</ThemeProvider>
<style>{`
@media (max-width: 768px) {
.main-content {
padding-top: 4rem !important;
padding-left: 1rem !important;
padding-right: 1rem !important;
}
}
`}</style>
</body>
</html>
);
}

5
app/mastodon/page.tsx Normal file
View File

@@ -0,0 +1,5 @@
import { redirect } from "next/navigation";
export default function MastodonPage() {
redirect("https://infosec.exchange/@denizbektas");
}

57
app/merhaba/page.tsx Normal file
View File

@@ -0,0 +1,57 @@
import type { Metadata } from "next";
export const metadata: Metadata = { title: "Merhaba" };
export default function MerhabaPage() {
return (
<div style={{ maxWidth: "100%" }}>
<div className="page-title">Merhaba</div>
<p style={{ fontSize: "0.8rem", color: "var(--text-muted)", marginBottom: "2rem" }}>
Bu sitenin amacını anlatan sayfa
</p>
<div className="card prose" style={{ marginBottom: "1rem" }}>
<h2>Neden bu site?</h2>
<p>
İnternette bir köşem olsun istedim. Sosyal medyanın gürültüsünden uzak, kendi sesimle
yazdığım, düşündüğüm ve öğrendiklerimi paylaştığım bir alan.
</p>
<p>
denizbektas.com.tr benim dijital bahçem. Burada blog yazıları, teknik infosec içerikleri,
kısa notlar, projeler ve daha fazlasını bulacaksınız.
</p>
<h2>Kim için?</h2>
<p>
Öncelikle <strong>kendim için</strong>. Bir şeyi yazmak, onu anlamaktır. Ama aynı zamanda:
</p>
<ul>
<li>Siber güvenliğe meraklı olanlar için</li>
<li>Red team / pentest yolculuğunda olanlar için</li>
<li>Türkçe teknik içerik arayanlar için</li>
<li>İnternet üzerinde kendi sesini bulmaya çalışanlar için</li>
</ul>
<h2>Ne bulacaksınız?</h2>
<ul>
<li><strong>Personal Blog</strong> Kişisel yazılar, kariyer notları, düşünceler</li>
<li><strong>Infosec Posts</strong> Teknik güvenlik yazıları, tool analizleri, CTF writeupları</li>
<li><strong>Notebook</strong> Anlık notlar, linkler, kısa düşünceler</li>
<li><strong>Seyir Defteri</strong> Hedefler ve ilerleme durumu</li>
<li><strong>Roadmap</strong> Red teamer olmak isteyenler için rehber</li>
</ul>
<h2>İletişim</h2>
<p>
Benimle konuşmak istersen <a href="mailto:info@denizbektas.com.tr">info@denizbektas.com.tr</a> adresine
yazabilir ya da Mastodon&apos;da bulabilirsin. PGP anahtarım{" "}
<a href="/public.pgp">burada</a>.
</p>
<blockquote>
&quot;The internet is for people who use it, not for people who just consume it.&quot;
</blockquote>
</div>
</div>
);
}

49
app/misyon/page.tsx Normal file
View File

@@ -0,0 +1,49 @@
import type { Metadata } from "next";
export const metadata: Metadata = { title: "Misyon" };
export default function MisyonPage() {
return (
<div style={{ maxWidth: "100%" }}>
<div className="page-title">Misyon</div>
<p style={{ fontSize: "0.8rem", color: "var(--text-muted)", marginBottom: "2rem" }}>
Neden yapıyorum, ne yapıyorum
</p>
<div className="card prose">
<h2>Neden?</h2>
<p>
Siber güvenlik sadece teknik bir alan değil. Sistemleri anlama, onları koruma ve
dijital dünyayı daha güvenli hale getirme misyonu. Bu misyon beni her sabah
bilgisayar başına getiriyor.
</p>
<h2>Ne Yapıyorum?</h2>
<p>
Saldırgan bakış ısıyla sistemleri test ediyorum. Red team operasyonları, penetrasyon
testleri, güvenlik değerlendirmeleri... Amacım ıkları bulmak savunmadan önce.
</p>
<h2>Bu Sitenin Misyonu</h2>
<ul>
<li><strong>Belgelemek:</strong> Öğrendiklerimi kayıt altına almak</li>
<li><strong>Paylaşmak:</strong> Türkçe teknik içerik üretmek</li>
<li><strong>İlham vermek:</strong> Bu alana girmek isteyenlere yol göstermek</li>
<li><strong>Şeffaf olmak:</strong> Yolculuğumu, başarıları ve başarısızlıkları ile ık paylaşmak</li>
</ul>
<h2>Değerler</h2>
<ul>
<li><strong>Etik:</strong> Sadece izinli sistemlerde çalışıyorum. Kötü niyetli aktörlere karşıyım.</li>
<li><strong>ık kaynak:</strong> Topluluğa geri vermek önemli</li>
<li><strong>Sürekli öğrenme:</strong> Bu alan durmadan değişiyor; ben de duruyorum</li>
<li><strong>Kalite:</strong> Az ama öz içerik</li>
</ul>
<blockquote>
&quot;Hack the planet but with ethics.&quot;
</blockquote>
</div>
</div>
);
}

View File

@@ -0,0 +1,44 @@
import type { Metadata } from "next";
import Link from "next/link";
import { getPost, getPosts } from "@/lib/posts";
import { notFound } from "next/navigation";
export async function generateStaticParams() {
return getPosts("notebook").map((p) => ({ slug: p.slug }));
}
export async function generateMetadata({ params }: { params: Promise<{ slug: string }> }): Promise<Metadata> {
const { slug } = await params;
const post = await getPost("notebook", slug);
if (!post) return {};
return { title: post.title, description: post.excerpt };
}
export default async function NotebookPostPage({ params }: { params: Promise<{ slug: string }> }) {
const { slug } = await params;
const post = await getPost("notebook", slug);
if (!post) notFound();
return (
<div style={{ maxWidth: "100%" }}>
<Link href="/notebook" style={{ fontSize: "0.78rem", color: "var(--text-muted)", display: "flex", alignItems: "center", gap: "0.3rem", marginBottom: "1.5rem" }}>
Notebook&apos;a Dön
</Link>
<article>
<header style={{ marginBottom: "1.5rem" }}>
<h1 style={{ fontSize: "1.3rem", fontWeight: 700, color: "var(--text)", marginBottom: "0.4rem" }}>
{post.title}
</h1>
<div style={{ display: "flex", alignItems: "center", gap: "0.75rem", flexWrap: "wrap" }}>
<span style={{ fontSize: "0.73rem", color: "var(--text-muted)" }}>
{new Date(post.date).toLocaleDateString("tr-TR", { year: "numeric", month: "long", day: "numeric" })}
</span>
{post.tags.map((t) => <span key={t} className="tag">{t}</span>)}
</div>
</header>
<div className="card prose" style={{ borderLeft: "3px solid var(--accent)" }} dangerouslySetInnerHTML={{ __html: post.content || "" }} />
</article>
</div>
);
}

47
app/notebook/page.tsx Normal file
View File

@@ -0,0 +1,47 @@
import type { Metadata } from "next";
import Link from "next/link";
import { getPosts } from "@/lib/posts";
export const metadata: Metadata = { title: "Notebook" };
export default function NotebookPage() {
const posts = getPosts("notebook");
return (
<div style={{ maxWidth: "100%" }}>
<div className="page-title">Notebook</div>
<p style={{ fontSize: "0.8rem", color: "var(--text-muted)", marginBottom: "2rem" }}>
Anlık düşünceler, kısa notlar twitter&apos;ın sessiz versiyonu
</p>
{posts.length === 0 ? (
<div className="card" style={{ color: "var(--text-muted)", fontSize: "0.85rem" }}>Henüz not yok.</div>
) : (
<div style={{ display: "flex", flexDirection: "column", gap: "0.75rem" }}>
{posts.map((post) => (
<article key={post.slug} className="card" style={{ borderLeft: "3px solid var(--accent)" }}>
<div style={{ display: "flex", alignItems: "flex-start", justifyContent: "space-between", gap: "1rem", marginBottom: "0.4rem" }}>
<Link href={`/notebook/${post.slug}`}>
<h2 style={{ fontSize: "0.9rem", fontWeight: 600, color: "var(--text)", lineHeight: 1.4 }}>
{post.title}
</h2>
</Link>
<span style={{ fontSize: "0.7rem", color: "var(--text-muted)", flexShrink: 0 }}>
{new Date(post.date).toLocaleDateString("tr-TR", { month: "short", day: "numeric" })}
</span>
</div>
<p style={{ fontSize: "0.82rem", color: "var(--text-muted)", lineHeight: 1.6 }}>
{post.excerpt}
</p>
{post.tags.length > 0 && (
<div style={{ display: "flex", gap: "0.3rem", flexWrap: "wrap", marginTop: "0.5rem" }}>
{post.tags.map((t) => <span key={t} className="tag">{t}</span>)}
</div>
)}
</article>
))}
</div>
)}
</div>
);
}

149
app/ozgecmis/page.tsx Normal file
View File

@@ -0,0 +1,149 @@
import type { Metadata } from "next";
export const metadata: Metadata = { title: "Özgeçmiş" };
export default function OzgecmisPage() {
return (
<div style={{ maxWidth: "100%" }}>
<div className="page-title">Özgeçmiş</div>
<p style={{ fontSize: "0.8rem", color: "var(--text-muted)", marginBottom: "2rem" }}>
CV formatında özgeçmiş
</p>
{/* Header */}
<div className="card" style={{ marginBottom: "1rem" }}>
<div style={{ display: "flex", alignItems: "flex-start", justifyContent: "space-between", flexWrap: "wrap", gap: "1rem" }}>
<div>
<h1 style={{ fontSize: "1.3rem", fontWeight: 800, color: "var(--text)", marginBottom: "0.25rem" }}>denizbektas</h1>
<div style={{ fontSize: "0.85rem", color: "var(--accent)", marginBottom: "0.5rem" }}>Siber Güvenlik Araştırmacısı & Red Teamer</div>
<div style={{ display: "flex", gap: "1rem", fontSize: "0.78rem", color: "var(--text-muted)", flexWrap: "wrap" }}>
<span> info@denizbektas.com.tr</span>
<span> @denizbektas@infosec.exchange</span>
<span> github.com/bugresearch</span>
</div>
</div>
<a href="/public.pgp" className="tag" style={{ fontSize: "0.65rem" }}>PGP KEY</a>
</div>
</div>
{/* Experience */}
<Section title="Deneyim" icon="▤">
<CVItem
title="Senior Penetration Tester"
org="[Şirket Adı]"
period="2023 — Devam"
items={[
"Web uygulama penetrasyon testleri ve güvenlik değerlendirmeleri",
"Red team operasyonları ve sosyal mühendislik simülasyonları",
"Active Directory güvenlik testleri",
"Güvenlik açığı raporlama ve remediation rehberliği",
]}
/>
<CVItem
title="Security Analyst"
org="[Şirket Adı]"
period="2021 — 2023"
items={[
"SOC operasyonları ve olay müdahale",
"SIEM kural geliştirme ve tuning",
"Vulnerability management programı",
]}
/>
</Section>
{/* Education */}
<Section title="Eğitim" icon="◎">
<CVItem
title="Bilgisayar Mühendisliği"
org="[Üniversite Adı]"
period="2017 — 2021"
items={["Lisans derecesi", "Bitirme projesi: Web uygulama güvenlik tarayıcı geliştirme"]}
/>
</Section>
{/* Certifications */}
<Section title="Sertifikalar" icon="◆">
<div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(200px, 1fr))", gap: "0.5rem" }}>
{[
{ name: "eJPT", org: "eLearnSecurity", year: "2022", status: "active" },
{ name: "CompTIA Security+", org: "CompTIA", year: "2021", status: "active" },
{ name: "OSCP", org: "OffSec", year: "2026 (hedef)", status: "pending" },
].map((cert) => (
<div key={cert.name} className="card" style={{ padding: "0.75rem" }}>
<div style={{ fontSize: "0.88rem", fontWeight: 600, color: cert.status === "pending" ? "var(--text-muted)" : "var(--accent)" }}>{cert.name}</div>
<div style={{ fontSize: "0.72rem", color: "var(--text-muted)" }}>{cert.org} · {cert.year}</div>
</div>
))}
</div>
</Section>
{/* Skills */}
<Section title="Teknik Beceriler" icon="⚔">
<div style={{ display: "flex", flexDirection: "column", gap: "0.75rem" }}>
{[
{ cat: "Pentest & Red Team", skills: ["Web App Testing", "Network Pentest", "AD Attack", "Red Team Ops", "Social Engineering"] },
{ cat: "Araçlar", skills: ["Burp Suite", "Nmap", "Metasploit", "BloodHound", "Cobalt Strike", "Ghidra"] },
{ cat: "Programlama", skills: ["Python", "Bash", "PowerShell", "C/C++", "Rust (öğreniyorum)"] },
{ cat: "OS & Platform", skills: ["Kali Linux", "macOS", "Windows", "Active Directory", "Docker"] },
].map((row) => (
<div key={row.cat}>
<div style={{ fontSize: "0.72rem", color: "var(--text-muted)", marginBottom: "0.35rem" }}>{row.cat}</div>
<div style={{ display: "flex", gap: "0.35rem", flexWrap: "wrap" }}>
{row.skills.map((s) => <span key={s} className="tag">{s}</span>)}
</div>
</div>
))}
</div>
</Section>
{/* Languages */}
<Section title="Diller" icon="◈">
<div style={{ display: "flex", flexDirection: "column", gap: "0.5rem" }}>
{[
{ lang: "Türkçe", level: "Ana dil" },
{ lang: "İngilizce", level: "İleri (C1)" },
].map((l) => (
<div key={l.lang} style={{ display: "flex", justifyContent: "space-between", fontSize: "0.85rem", padding: "0.4rem 0", borderBottom: "1px solid var(--border)" }}>
<span style={{ color: "var(--text)" }}>{l.lang}</span>
<span style={{ color: "var(--text-muted)" }}>{l.level}</span>
</div>
))}
</div>
</Section>
</div>
);
}
function Section({ title, icon, children }: { title: string; icon: string; children: React.ReactNode }) {
return (
<div style={{ marginBottom: "1.5rem" }}>
<div className="section-header">
<span style={{ color: "var(--accent)", marginRight: "0.4rem" }}>{icon}</span>
{title}
</div>
{children}
</div>
);
}
function CVItem({ title, org, period, items }: { title: string; org: string; period: string; items: string[] }) {
return (
<div className="card" style={{ marginBottom: "0.5rem" }}>
<div style={{ display: "flex", alignItems: "flex-start", justifyContent: "space-between", flexWrap: "wrap", gap: "0.5rem", marginBottom: "0.5rem" }}>
<div>
<div style={{ fontWeight: 600, fontSize: "0.9rem", color: "var(--text)" }}>{title}</div>
<div style={{ fontSize: "0.78rem", color: "var(--accent)" }}>{org}</div>
</div>
<span style={{ fontSize: "0.72rem", color: "var(--text-muted)" }}>{period}</span>
</div>
<ul style={{ listStyle: "none", display: "flex", flexDirection: "column", gap: "0.25rem" }}>
{items.map((item) => (
<li key={item} style={{ fontSize: "0.8rem", color: "var(--text-muted)", display: "flex", gap: "0.4rem" }}>
<span style={{ color: "var(--accent)", flexShrink: 0 }}></span>
{item}
</li>
))}
</ul>
</div>
);
}

View File

@@ -1,65 +1,215 @@
import Image from "next/image";
import Link from "next/link";
import { getPosts } from "@/lib/posts";
import { getActivity } from "@/lib/activity";
export default function Home() {
const blogPosts = getPosts("blog").slice(0, 3);
const infosecPosts = getPosts("infosec").slice(0, 3);
const notes = getPosts("notebook").slice(0, 3);
const activities = getActivity().slice(0, 5);
return (
<div className="flex flex-col flex-1 items-center justify-center bg-zinc-50 font-sans dark:bg-black">
<main className="flex flex-1 w-full max-w-3xl flex-col items-center justify-between py-32 px-16 bg-white dark:bg-black sm:items-start">
<Image
className="dark:invert"
src="/next.svg"
alt="Next.js logo"
width={100}
height={20}
priority
/>
<div className="flex flex-col items-center gap-6 text-center sm:items-start sm:text-left">
<h1 className="max-w-xs text-3xl font-semibold leading-10 tracking-tight text-black dark:text-zinc-50">
To get started, edit the page.tsx file.
</h1>
<p className="max-w-md text-lg leading-8 text-zinc-600 dark:text-zinc-400">
Looking for a starting point or more instructions? Head over to{" "}
<a
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
className="font-medium text-zinc-950 dark:text-zinc-50"
>
Templates
</a>{" "}
or the{" "}
<a
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
className="font-medium text-zinc-950 dark:text-zinc-50"
>
Learning
</a>{" "}
center.
</p>
<div style={{ maxWidth: "100%" }}>
{/* Hero */}
<div className="card" style={{ marginBottom: "2rem" }}>
<div style={{ display: "flex", alignItems: "center", gap: "0.5rem", marginBottom: "0.75rem" }}>
<span style={{ color: "var(--accent)", fontSize: "0.8rem" }}>root@denizbektas.com.tr:~$</span>
<span style={{ color: "var(--text)", fontSize: "0.8rem" }}>whoami</span>
</div>
<div className="flex flex-col gap-4 text-base font-medium sm:flex-row">
<a
className="flex h-12 w-full items-center justify-center gap-2 rounded-full bg-foreground px-5 text-background transition-colors hover:bg-[#383838] dark:hover:bg-[#ccc] md:w-[158px]"
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
<Image
className="dark:invert"
src="/vercel.svg"
alt="Vercel logomark"
width={16}
height={16}
/>
Deploy Now
</a>
<a
className="flex h-12 w-full items-center justify-center rounded-full border border-solid border-black/[.08] px-5 transition-colors hover:border-transparent hover:bg-black/[.04] dark:border-white/[.145] dark:hover:bg-[#1a1a1a] md:w-[158px]"
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
Documentation
</a>
<h1 style={{ fontSize: "1.6rem", fontWeight: 800, color: "var(--accent)", marginBottom: "0.5rem" }}>
denizbektas
</h1>
<p style={{ color: "var(--text-muted)", fontSize: "0.875rem", lineHeight: 1.7, maxWidth: "600px" }}>
Siber güvenlik araştırmacısı, red teamer, CTF oyuncusu. Sistemlerin nasıl kırıldığını anlayarak
onları nasıl koruyacağımızı öğreniyoruz. Bu site o yolculuğun kayıtlarıdır.
</p>
<div style={{ display: "flex", gap: "0.5rem", marginTop: "1rem", flexWrap: "wrap" }}>
<span className="tag">red team</span>
<span className="tag">pentest</span>
<span className="tag">CTF</span>
<span className="tag">OSINT</span>
<span className="tag">malware analysis</span>
</div>
</main>
<div style={{ marginTop: "1rem", display: "flex", gap: "1rem", fontSize: "0.8rem" }}>
<Link href="/merhaba" style={{ color: "var(--accent)" }}> Merhaba</Link>
<Link href="/hakkimda" style={{ color: "var(--text-muted)" }}>Hakkımda</Link>
<Link href="/iletisim" style={{ color: "var(--text-muted)" }}>İletişim</Link>
</div>
</div>
{/* Grid */}
<div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(280px, 1fr))", gap: "1rem" }}>
{/* Blog Widget */}
<WidgetCard title="Personal Blog" href="/blog" icon="✍">
{blogPosts.length === 0 ? (
<EmptyState text="Henüz yazı yok" />
) : (
<ul style={{ listStyle: "none", display: "flex", flexDirection: "column", gap: "0.75rem" }}>
{blogPosts.map((p) => (
<li key={p.slug}>
<Link href={`/blog/${p.slug}`} style={{ color: "var(--text)", fontSize: "0.82rem", display: "block", lineHeight: 1.4 }}>
{p.title}
</Link>
<span style={{ fontSize: "0.7rem", color: "var(--text-muted)" }}>{formatDate(p.date)}</span>
</li>
))}
</ul>
)}
</WidgetCard>
{/* Infosec Widget */}
<WidgetCard title="Infosec Posts" href="/infosec" icon="⚔">
{infosecPosts.length === 0 ? (
<EmptyState text="Henüz yazı yok" />
) : (
<ul style={{ listStyle: "none", display: "flex", flexDirection: "column", gap: "0.75rem" }}>
{infosecPosts.map((p) => (
<li key={p.slug}>
<Link href={`/infosec/${p.slug}`} style={{ color: "var(--text)", fontSize: "0.82rem", display: "block", lineHeight: 1.4 }}>
{p.title}
</Link>
<div style={{ display: "flex", gap: "0.25rem", flexWrap: "wrap", marginTop: "0.2rem" }}>
{p.tags.slice(0, 2).map((t) => <span key={t} className="tag">{t}</span>)}
</div>
</li>
))}
</ul>
)}
</WidgetCard>
{/* Notebook Widget */}
<WidgetCard title="Notebook" href="/notebook" icon="◎">
{notes.length === 0 ? (
<EmptyState text="Henüz not yok" />
) : (
<ul style={{ listStyle: "none", display: "flex", flexDirection: "column", gap: "0.6rem" }}>
{notes.map((p) => (
<li key={p.slug}>
<Link href={`/notebook/${p.slug}`} style={{ color: "var(--text)", fontSize: "0.82rem" }}>
{p.title}
</Link>
<br />
<span style={{ fontSize: "0.7rem", color: "var(--text-muted)" }}>{p.excerpt.slice(0, 60)}...</span>
</li>
))}
</ul>
)}
</WidgetCard>
{/* Activity Widget */}
<WidgetCard title="Son Aktivite" href="/aktivite" icon="▶">
<ul style={{ listStyle: "none", display: "flex", flexDirection: "column" }}>
{activities.map((a) => (
<li key={a.id} className="terminal-line" style={{ fontSize: "0.75rem" }}>
<span className="prompt" style={{ flexShrink: 0, fontSize: "0.65rem" }}>
{typeIcon(a.type)}
</span>
<span style={{ flex: 1 }}>
{a.link ? <Link href={a.link}>{a.message}</Link> : a.message}
</span>
</li>
))}
</ul>
</WidgetCard>
{/* Now Widget */}
<WidgetCard title="Şu Anda" href="/su-anda" icon="◉">
<div style={{ fontSize: "0.82rem", color: "var(--text-muted)", lineHeight: 1.9 }}>
<p>🔴 <strong style={{ color: "var(--text)" }}>Odak:</strong> Red team metodolojileri</p>
<p>📖 <strong style={{ color: "var(--text)" }}>Okuma:</strong> The Hacker Playbook 3</p>
<p>🎯 <strong style={{ color: "var(--text)" }}>Hedef:</strong> OSCP sertifikası</p>
<p>🎵 <strong style={{ color: "var(--text)" }}>Dinleme:</strong> Darksynth</p>
</div>
</WidgetCard>
{/* RSS Widget */}
<WidgetCard title="RSS Beslemeleri" href="/rss-beslemeleri" icon="◈">
<div style={{ display: "flex", flexDirection: "column", gap: "0.5rem" }}>
{[
{ label: "Tüm İçerikler", href: "/api/rss/all" },
{ label: "Blog", href: "/api/rss/blog" },
{ label: "Infosec", href: "/api/rss/infosec" },
{ label: "Podcast", href: "/api/rss/podcast" },
].map((r) => (
<a key={r.href} href={r.href} style={{ display: "flex", alignItems: "center", gap: "0.5rem", fontSize: "0.8rem", color: "var(--text-muted)" }}>
<span style={{ color: "#f26522", fontSize: "0.7rem" }}></span>
{r.label}
</a>
))}
</div>
</WidgetCard>
{/* Statboard Widget */}
<WidgetCard title="Statboard" href="/statboard" icon="▦">
<div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: "0.5rem" }}>
{[
{ label: "Blog Yazısı", value: "1" },
{ label: "Infosec Yazı", value: "1" },
{ label: "CTF Çözümü", value: "47" },
{ label: "Çay ☕", value: "∞" },
].map((s) => (
<div key={s.label} style={{ textAlign: "center", padding: "0.5rem", background: "var(--bg)", borderRadius: "4px", border: "1px solid var(--border)" }}>
<div style={{ fontSize: "1.1rem", fontWeight: 700, color: "var(--accent)" }}>{s.value}</div>
<div style={{ fontSize: "0.65rem", color: "var(--text-muted)" }}>{s.label}</div>
</div>
))}
</div>
</WidgetCard>
{/* Projeler Widget */}
<WidgetCard title="Projeler" href="/projeler" icon="◈">
<div style={{ display: "flex", flexDirection: "column", gap: "0.6rem" }}>
<ProjectItem name="denizbektas.com.tr" desc="Bu site — kişisel alan" status="active" />
<ProjectItem name="recon-toolkit" desc="Otomasyon keşif aracı" status="wip" />
<ProjectItem name="ctf-writeups" desc="CTF çözüm yazıları" status="active" />
</div>
</WidgetCard>
</div>
</div>
);
}
function WidgetCard({ title, href, icon, children }: { title: string; href: string; icon: string; children: React.ReactNode }) {
return (
<div className="card" style={{ display: "flex", flexDirection: "column" }}>
<div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: "0.75rem" }}>
<div style={{ display: "flex", alignItems: "center", gap: "0.4rem", fontSize: "0.75rem", fontWeight: 700, color: "var(--text)", letterSpacing: "0.02em" }}>
<span style={{ color: "var(--accent)", fontSize: "0.7rem" }}>{icon}</span>
{title}
</div>
<Link href={href} style={{ fontSize: "0.65rem", color: "var(--text-muted)" }}>tümü </Link>
</div>
{children}
</div>
);
}
function EmptyState({ text }: { text: string }) {
return <div style={{ fontSize: "0.8rem", color: "var(--text-muted)", fontStyle: "italic" }}>{text}</div>;
}
function ProjectItem({ name, desc, status }: { name: string; desc: string; status: string }) {
const colors: Record<string, string> = { active: "#00d4aa", wip: "#f59e0b", archived: "#64748b" };
return (
<div style={{ display: "flex", alignItems: "flex-start", gap: "0.5rem" }}>
<span style={{ color: colors[status] || "var(--text-muted)", fontSize: "0.5rem", marginTop: "0.3rem", flexShrink: 0 }}></span>
<div>
<div style={{ fontSize: "0.82rem", color: "var(--text)" }}>{name}</div>
<div style={{ fontSize: "0.7rem", color: "var(--text-muted)" }}>{desc}</div>
</div>
</div>
);
}
function typeIcon(type: string) {
const icons: Record<string, string> = {
post: "✍", notebook: "◎", infosec: "⚔", project: "◈", link: "⊞", update: "▲", system: "⚙",
};
return icons[type] || "▶";
}
function formatDate(date: string) {
return new Date(date).toLocaleDateString("tr-TR", { year: "numeric", month: "short", day: "numeric" });
}

80
app/podcast/page.tsx Normal file
View File

@@ -0,0 +1,80 @@
import type { Metadata } from "next";
export const metadata: Metadata = { title: "Podcast" };
export default function PodcastPage() {
return (
<div style={{ maxWidth: "100%" }}>
<div className="page-title">Podcast</div>
<p style={{ fontSize: "0.8rem", color: "var(--text-muted)", marginBottom: "2rem" }}>
Türkçe siber güvenlik podcast&apos;i
</p>
<div className="card" style={{ marginBottom: "1.5rem", borderLeft: "3px solid var(--accent)" }}>
<div style={{ display: "flex", alignItems: "center", gap: "0.5rem", marginBottom: "1rem" }}>
<div style={{ width: "48px", height: "48px", background: "var(--bg)", border: "2px solid var(--accent)", borderRadius: "8px", display: "flex", alignItems: "center", justifyContent: "center", fontSize: "1.5rem" }}>
</div>
<div>
<div style={{ fontWeight: 700, fontSize: "1rem", color: "var(--text)" }}>Deniz Bektaş Podcast</div>
<div style={{ fontSize: "0.75rem", color: "var(--text-muted)" }}>Siber güvenlik, red team ve hacker kültürü</div>
</div>
</div>
<div style={{ fontSize: "0.82rem", color: "var(--text-muted)", lineHeight: 1.7, marginBottom: "1rem" }}>
<p style={{ marginBottom: "0" }}>
🚧 Yakında başlıyor. Türkçe teknik siber güvenlik podcast&apos;i.
Konular: red team hikayeleri, tool analizleri, kariyer tavsiyeleri, sektör haberleri.
</p>
</div>
<div style={{ display: "flex", gap: "0.5rem", flexWrap: "wrap" }}>
<span className="tag">yakında</span>
<span className="tag">türkçe</span>
<span className="tag">infosec</span>
<span className="tag">red team</span>
</div>
</div>
<div style={{ marginBottom: "1.5rem" }}>
<div className="section-header">Takip Kanalları</div>
<div style={{ display: "flex", flexDirection: "column", gap: "0.5rem" }}>
{[
{ name: "RSS Beslemesi", href: "/api/rss/podcast", icon: "⊞", desc: "Doğrudan RSS ile takip" },
{ name: "Spotify", href: "#", icon: "◉", desc: "Spotify Podcasts — yakında" },
{ name: "Apple Podcasts", href: "#", icon: "◉", desc: "Apple Podcasts — yakında" },
{ name: "YouTube", href: "#", icon: "▶", desc: "Video formatı — yakında" },
].map((c) => (
<a key={c.name} href={c.href} className="card" style={{ display: "flex", alignItems: "center", gap: "0.75rem", opacity: c.href === "#" ? 0.5 : 1, cursor: c.href === "#" ? "not-allowed" : "pointer" }}>
<span style={{ color: "var(--accent)", fontSize: "1rem", width: "24px", textAlign: "center" }}>{c.icon}</span>
<div>
<div style={{ fontSize: "0.85rem", fontWeight: 600, color: "var(--text)" }}>{c.name}</div>
<div style={{ fontSize: "0.72rem", color: "var(--text-muted)" }}>{c.desc}</div>
</div>
</a>
))}
</div>
</div>
<div className="card prose">
<h2>Format</h2>
<ul>
<li>Dil: Türkçe</li>
<li>Süre: 30-60 dakika</li>
<li>Sıklık: İki haftada bir</li>
<li>Format: Tekli bölüm + zaman zaman konuk</li>
</ul>
<h2>Konu Planı</h2>
<ul>
<li>Red team operasyonları sahadan hikayeler</li>
<li>CTF yarışmaları nasıl katılırsınız, nasıl öğrenirsiniz</li>
<li>Güvenlik sertifikaları gerçekten değer mi?</li>
<li>OSCP yolculuğu</li>
<li>Kariyer tavsiyeleri siber güvenliğe nasıl girilir</li>
<li>Sektör haberleri ve büyük olayların analizi</li>
</ul>
</div>
</div>
);
}

123
app/projeler/page.tsx Normal file
View File

@@ -0,0 +1,123 @@
import type { Metadata } from "next";
export const metadata: Metadata = { title: "Projeler" };
interface Project {
name: string;
description: string;
status: "active" | "wip" | "archived" | "planned";
tags: string[];
url?: string;
github?: string;
}
const projects: Project[] = [
{
name: "denizbektas.com.tr",
description: "Bu site. Next.js, TypeScript, Markdown tabanlı kişisel alan. Açık kaynak.",
status: "active",
tags: ["nextjs", "typescript", "website"],
github: "https://github.com/bugresearch/denizbektas.com.tr",
},
{
name: "recon-toolkit",
description: "Python ile geliştirilmiş modüler recon otomasyon aracı. Subdomain enumeration, port scan, tech fingerprinting.",
status: "wip",
tags: ["python", "recon", "osint", "automation"],
github: "https://github.com/bugresearch/recon-toolkit",
},
{
name: "ctf-writeups",
description: "HackTheBox ve çeşitli CTF yarışmalarından çözüm yazıları koleksiyonu.",
status: "active",
tags: ["ctf", "writeup", "hactkthebox"],
github: "https://github.com/bugresearch/ctf-writeups",
},
{
name: "nuclei-templates",
description: "Özel Nuclei tarama şablonları. Web uygulamaları için özelleştirilmiş güvenlik testleri.",
status: "active",
tags: ["nuclei", "pentest", "templates"],
github: "https://github.com/bugresearch/nuclei-templates",
},
{
name: "implant-rs",
description: "Rust ile yazılan minimal C2 implant — eğitim ve araştırma amaçlı.",
status: "wip",
tags: ["rust", "c2", "red-team", "research"],
},
{
name: "wordlist-tr",
description: "Türkçe hedef sistemler için özelleştirilmiş wordlist koleksiyonu.",
status: "planned",
tags: ["wordlist", "pentest", "turkish"],
},
];
const statusConfig = {
active: { label: "Aktif", color: "#00d4aa", icon: "●" },
wip: { label: "Yapım Aşamasında", color: "#f59e0b", icon: "◉" },
archived: { label: "Arşivlendi", color: "#64748b", icon: "◎" },
planned: { label: "Planlandı", color: "#7c6af7", icon: "◇" },
};
export default function ProjelerPage() {
return (
<div style={{ maxWidth: "100%" }}>
<div className="page-title">Projeler</div>
<p style={{ fontSize: "0.8rem", color: "var(--text-muted)", marginBottom: "2rem" }}>
Üzerinde çalıştığım ve geliştirdiğim projeler
</p>
<div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(320px, 1fr))", gap: "0.75rem" }}>
{projects.map((p) => {
const cfg = statusConfig[p.status];
return (
<div key={p.name} className="card">
<div style={{ display: "flex", alignItems: "flex-start", justifyContent: "space-between", gap: "0.5rem", marginBottom: "0.5rem" }}>
<h3 style={{ fontSize: "0.95rem", fontWeight: 700, color: "var(--text)", fontFamily: "monospace" }}>{p.name}</h3>
<span style={{
fontSize: "0.6rem",
display: "flex",
alignItems: "center",
gap: "0.25rem",
color: cfg.color,
border: `1px solid ${cfg.color}`,
padding: "0.1rem 0.4rem",
borderRadius: "3px",
flexShrink: 0,
fontWeight: 700,
textTransform: "uppercase",
}}>
<span style={{ fontSize: "0.4rem" }}>{cfg.icon}</span>
{cfg.label}
</span>
</div>
<p style={{ fontSize: "0.8rem", color: "var(--text-muted)", lineHeight: 1.6, marginBottom: "0.75rem" }}>
{p.description}
</p>
<div style={{ display: "flex", gap: "0.3rem", flexWrap: "wrap", marginBottom: "0.75rem" }}>
{p.tags.map((t) => <span key={t} className="tag">{t}</span>)}
</div>
<div style={{ display: "flex", gap: "0.75rem" }}>
{p.github && (
<a href={p.github} target="_blank" rel="noopener noreferrer" style={{ fontSize: "0.75rem", display: "flex", alignItems: "center", gap: "0.3rem" }}>
<span style={{ fontSize: "0.65rem" }}></span> GitHub
</a>
)}
{p.url && (
<a href={p.url} target="_blank" rel="noopener noreferrer" style={{ fontSize: "0.75rem", display: "flex", alignItems: "center", gap: "0.3rem" }}>
<span style={{ fontSize: "0.65rem" }}></span> Demo
</a>
)}
</div>
</div>
);
})}
</div>
</div>
);
}

14
app/public.pgp/route.ts Normal file
View File

@@ -0,0 +1,14 @@
import { NextResponse } from "next/server";
export async function GET() {
// Replace with your actual PGP public key
const pgpKey = `-----BEGIN PGP PUBLIC KEY BLOCK-----
mQINBGX... (replace with your actual PGP public key)
-----END PGP PUBLIC KEY BLOCK-----
`;
return new NextResponse(pgpKey, {
headers: { "Content-Type": "text/plain; charset=utf-8" },
});
}

231
app/roadmap/page.tsx Normal file
View File

@@ -0,0 +1,231 @@
import type { Metadata } from "next";
export const metadata: Metadata = { title: "Red Teamer Roadmap" };
interface RoadmapItem {
title: string;
description: string;
resources: { name: string; url?: string }[];
level: "beginner" | "intermediate" | "advanced";
}
interface Phase {
phase: number;
title: string;
subtitle: string;
duration: string;
items: RoadmapItem[];
}
const phases: Phase[] = [
{
phase: 1,
title: "Temel Kavramlar",
subtitle: "Foundation",
duration: "1-3 ay",
items: [
{
title: "Ağ Temelleri",
description: "TCP/IP, OSI modeli, DNS, HTTP/S, temel protokoller",
resources: [
{ name: "TryHackMe — Pre-Security path" },
{ name: "Professor Messer Network+", url: "https://www.professormesser.com" },
{ name: "Practical Networking", url: "https://www.practicalnetworking.net" },
],
level: "beginner",
},
{
title: "Linux Temelleri",
description: "Komut satırı, dosya sistemi, izinler, scripting",
resources: [
{ name: "OverTheWire: Bandit", url: "https://overthewire.org/wargames/bandit" },
{ name: "TryHackMe — Linux Fundamentals" },
{ name: "The Linux Command Line (kitap)" },
],
level: "beginner",
},
{
title: "Python ile Scripting",
description: "Temel Python, otomasyon, araç geliştirme",
resources: [
{ name: "Automate the Boring Stuff with Python", url: "https://automatetheboringstuff.com" },
{ name: "Violent Python (kitap)" },
],
level: "beginner",
},
],
},
{
phase: 2,
title: "Güvenlik Temelleri",
subtitle: "Security Basics",
duration: "2-4 ay",
items: [
{
title: "Web Uygulama Güvenliği",
description: "OWASP Top 10, SQL injection, XSS, CSRF, authentication bypass",
resources: [
{ name: "PortSwigger Web Academy", url: "https://portswigger.net/web-security" },
{ name: "OWASP WebGoat", url: "https://owasp.org/www-project-webgoat" },
{ name: "The Web Application Hacker's Handbook" },
],
level: "intermediate",
},
{
title: "Pentest Temelleri",
description: "Metodoloji, keşif, tarama, exploitation, raporlama",
resources: [
{ name: "TryHackMe — Jr Penetration Tester path" },
{ name: "eJPT (eLearnSecurity)" },
{ name: "Penetration Testing (Georgia Weidman)" },
],
level: "intermediate",
},
{
title: "Kriptografi Temelleri",
description: "Şifreleme algoritmaları, hash fonksiyonları, PKI",
resources: [
{ name: "CryptoHack", url: "https://cryptohack.org" },
{ name: "Cryptopals Challenges", url: "https://cryptopals.com" },
],
level: "intermediate",
},
],
},
{
phase: 3,
title: "Offensive Security",
subtitle: "Going Deeper",
duration: "3-6 ay",
items: [
{
title: "Active Directory Saldırıları",
description: "Kerberoasting, Pass-the-Hash, DCSync, BloodHound, lateral movement",
resources: [
{ name: "HackTheBox — AD machines" },
{ name: "Red Team Notes — AD", url: "https://www.ired.team" },
{ name: "Impacket tools" },
],
level: "advanced",
},
{
title: "OSCP Hazırlığı",
description: "Buffer overflow, privilege escalation, pivoting, tunneling",
resources: [
{ name: "OffSec PEN-200 course" },
{ name: "HackTheBox — OSCP-like machines" },
{ name: "The Hacker Playbook 3" },
],
level: "advanced",
},
{
title: "Malware Analizi",
description: "Statik ve dinamik analiz, reverse engineering, sandbox",
resources: [
{ name: "Malware Traffic Analysis", url: "https://malware-traffic-analysis.net" },
{ name: "Ghidra kullanımı" },
{ name: "Practical Malware Analysis (kitap)" },
],
level: "advanced",
},
],
},
{
phase: 4,
title: "Red Team Operasyonları",
subtitle: "Professional Level",
duration: "Süregelen",
items: [
{
title: "C2 Framework & İmplant Geliştirme",
description: "Cobalt Strike, Havoc, Sliver — C2 mimarisi ve özel implant yazımı",
resources: [
{ name: "Red Team Development and Operations (kitap)" },
{ name: "Sektor7 courses", url: "https://institute.sektor7.net" },
{ name: "VX Underground malware samples" },
],
level: "advanced",
},
{
title: "Physical & Social Engineering",
description: "Fiziksel saldırılar, phishing kampanyaları, vishing",
resources: [
{ name: "The Art of Intrusion (kitap)" },
{ name: "Hacking: The Art of Exploitation" },
],
level: "advanced",
},
],
},
];
const levelColors = { beginner: "#22c55e", intermediate: "#f59e0b", advanced: "#ef4444" };
const phaseColors = ["#00d4aa", "#7c6af7", "#f59e0b", "#ef4444"];
export default function RoadmapPage() {
return (
<div style={{ maxWidth: "100%" }}>
<div className="page-title">Red Teamer Roadmap</div>
<p style={{ fontSize: "0.8rem", color: "var(--text-muted)", marginBottom: "0.5rem" }}>
Red teamer olmak isteyenler için kişisel rehberim
</p>
<div style={{ fontSize: "0.75rem", color: "var(--text-muted)", marginBottom: "2rem", padding: "0.6rem 0.75rem", background: "var(--bg-card)", border: "1px solid var(--border)", borderRadius: "4px" }}>
Bu yalnızca benim izlediğim yol. Herkes farklı öğrenir. Ayrıca: her zaman etik ve yasal sınırlar içinde kalın.
</div>
<div style={{ display: "flex", flexDirection: "column", gap: "2rem" }}>
{phases.map((phase, pi) => (
<div key={phase.phase}>
{/* Phase Header */}
<div style={{ display: "flex", alignItems: "center", gap: "0.75rem", marginBottom: "1rem", paddingBottom: "0.75rem", borderBottom: `2px solid ${phaseColors[pi]}` }}>
<div style={{ width: "32px", height: "32px", background: phaseColors[pi], color: "#000", borderRadius: "4px", display: "flex", alignItems: "center", justifyContent: "center", fontWeight: 800, fontSize: "0.9rem", flexShrink: 0 }}>
{phase.phase}
</div>
<div>
<div style={{ fontWeight: 700, fontSize: "1rem", color: "var(--text)" }}>{phase.title}</div>
<div style={{ fontSize: "0.72rem", color: "var(--text-muted)" }}>{phase.subtitle} · {phase.duration}</div>
</div>
</div>
<div style={{ display: "flex", flexDirection: "column", gap: "0.75rem" }}>
{phase.items.map((item) => (
<div key={item.title} className="card">
<div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: "0.4rem" }}>
<h3 style={{ fontSize: "0.9rem", fontWeight: 600, color: "var(--text)" }}>{item.title}</h3>
<span style={{
fontSize: "0.6rem",
padding: "0.1rem 0.4rem",
borderRadius: "3px",
fontWeight: 700,
color: levelColors[item.level],
border: `1px solid ${levelColors[item.level]}`,
textTransform: "uppercase",
}}>
{item.level}
</span>
</div>
<p style={{ fontSize: "0.8rem", color: "var(--text-muted)", marginBottom: "0.75rem" }}>{item.description}</p>
<div>
<div style={{ fontSize: "0.65rem", color: "var(--text-muted)", marginBottom: "0.3rem", textTransform: "uppercase", letterSpacing: "0.08em" }}>Kaynaklar</div>
<ul style={{ listStyle: "none", display: "flex", flexDirection: "column", gap: "0.2rem" }}>
{item.resources.map((r) => (
<li key={r.name} style={{ fontSize: "0.78rem", display: "flex", alignItems: "center", gap: "0.4rem" }}>
<span style={{ color: "var(--accent)", fontSize: "0.6rem" }}></span>
{r.url ? (
<a href={r.url} target="_blank" rel="noopener noreferrer">{r.name}</a>
) : (
<span style={{ color: "var(--text-muted)" }}>{r.name}</span>
)}
</li>
))}
</ul>
</div>
</div>
))}
</div>
</div>
))}
</div>
</div>
);
}

18
app/robots.txt/route.ts Normal file
View File

@@ -0,0 +1,18 @@
import { NextResponse } from "next/server";
export async function GET() {
const content = `User-agent: *
Allow: /
Disallow: /api/
Sitemap: https://denizbektas.com.tr/sitemap.xml
# Hi! If you're a human reading this, check out /humans.txt
# If you're a security researcher, check out /security.txt
`;
return new NextResponse(content, {
headers: { "Content-Type": "text/plain; charset=utf-8" },
});
}

View File

@@ -0,0 +1,116 @@
import type { Metadata } from "next";
export const metadata: Metadata = { title: "RSS Beslemeleri" };
const feeds = [
{
name: "Tüm İçerikler",
url: "/api/rss/all",
desc: "Blog, infosec yazıları ve notebook notlarının tamamı tek beslemede",
icon: "⊞",
},
{
name: "Personal Blog",
url: "/api/rss/blog",
desc: "Yalnızca kişisel blog yazıları",
icon: "✍",
},
{
name: "Infosec Posts",
url: "/api/rss/infosec",
desc: "Yalnızca teknik güvenlik yazıları",
icon: "⚔",
},
{
name: "Podcast",
url: "/api/rss/podcast",
desc: "Podcast bölümleri — yakında",
icon: "◉",
},
];
export default function RssBeslemeleriPage() {
return (
<div style={{ maxWidth: "100%" }}>
<div className="page-title">RSS Beslemeleri</div>
<p style={{ fontSize: "0.8rem", color: "var(--text-muted)", marginBottom: "2rem" }}>
İçerikleri RSS ile takip edin algoritmalar olmadan
</p>
{/* Feed List */}
<div style={{ display: "flex", flexDirection: "column", gap: "0.75rem", marginBottom: "2rem" }}>
{feeds.map((feed) => (
<div key={feed.name} className="card">
<div style={{ display: "flex", alignItems: "center", gap: "1rem" }}>
<div style={{ width: "36px", height: "36px", background: "#f26522", borderRadius: "6px", display: "flex", alignItems: "center", justifyContent: "center", color: "#fff", fontSize: "1rem", flexShrink: 0 }}>
{feed.icon}
</div>
<div style={{ flex: 1 }}>
<div style={{ fontSize: "0.88rem", fontWeight: 600, color: "var(--text)", marginBottom: "0.15rem" }}>{feed.name}</div>
<div style={{ fontSize: "0.75rem", color: "var(--text-muted)" }}>{feed.desc}</div>
</div>
<a
href={feed.url}
style={{ fontSize: "0.75rem", color: "var(--accent)", fontWeight: 600, display: "flex", alignItems: "center", gap: "0.25rem", flexShrink: 0 }}
>
Abone Ol
</a>
</div>
</div>
))}
</div>
{/* What is RSS */}
<div className="card prose">
<h2>RSS Nedir?</h2>
<p>
RSS (Really Simple Syndication), web sitelerinin yeni içeriklerini otomatik olarak
takipçilerine bildirmesini sağlayan bir teknolojidir. 2000&apos;li yılların başında
popülerleşen bu teknoloji, günümüzde hâlâ aktif olarak kullanılmaktadır.
</p>
<h2>Neden RSS?</h2>
<ul>
<li><strong>Algoritma yok:</strong> Hangi içeriği göreceğinizi siz seçersiniz</li>
<li><strong>Reklam yok:</strong> Doğrudan içerik, gürültüsüz</li>
<li><strong>Gizlilik:</strong> Okuma alışkanlıklarınız üçüncü taraflarla paylaşılmaz</li>
<li><strong>Merkezi değil:</strong> Tek platform bağımlılığı yok</li>
<li><strong>Hız:</strong> Yeni içerikler anında ulaşır</li>
</ul>
<h2>Nasıl Kullanılır?</h2>
<p>
Bir RSS okuyucusuna ihtiyacınız var. Önerilen okuyucular:
</p>
<ul>
<li><strong>Miniflux</strong> Self-hosted, minimalist, ık kaynak</li>
<li><strong>Feedbin</strong> Bulut tabanlı, güzel arayüz</li>
<li><strong>NetNewsWire</strong> macOS/iOS için ücretsiz</li>
<li><strong>Reeder</strong> iOS/macOS için ücretli ama kaliteli</li>
</ul>
<p>
RSS okuyucunuzu ın, yukarıdaki feed URL&apos;lerinden birini kopyalayın ve
okuyucunuza ekleyin. Artık yeni içerikler otomatik olarak gelecek.
</p>
<h2>OPML Dosyası</h2>
<p>
Tüm beslemeleri tek seferde eklemek için OPML dosyasını indirin:
</p>
<pre>{`<opml version="2.0">
<body>
<outline text="denizbektas.com.tr Feeds">
<outline type="rss" text="Tüm İçerikler"
xmlUrl="https://denizbektas.com.tr/api/rss/all"/>
<outline type="rss" text="Blog"
xmlUrl="https://denizbektas.com.tr/api/rss/blog"/>
<outline type="rss" text="Infosec"
xmlUrl="https://denizbektas.com.tr/api/rss/infosec"/>
</outline>
</body>
</opml>`}</pre>
</div>
</div>
);
}

23
app/security.txt/route.ts Normal file
View File

@@ -0,0 +1,23 @@
import { NextResponse } from "next/server";
export async function GET() {
const content = `Contact: mailto:info@denizbektas.com.tr
Contact: https://infosec.exchange/@denizbektas
Encryption: https://denizbektas.com.tr/public.pgp
Preferred-Languages: tr, en
Canonical: https://denizbektas.com.tr/security.txt
# Responsible Disclosure Policy
# Please report security vulnerabilities to info@denizbektas.com.tr
# Use PGP encryption for sensitive reports
# We will acknowledge receipt within 48 hours
# We do not offer a bug bounty program at this time
# Please do not disclose publicly before we have addressed the issue
Expires: 2027-04-03T00:00:00.000Z
`;
return new NextResponse(content, {
headers: { "Content-Type": "text/plain; charset=utf-8" },
});
}

152
app/seyir-defteri/page.tsx Normal file
View File

@@ -0,0 +1,152 @@
import type { Metadata } from "next";
export const metadata: Metadata = { title: "Kaptanın Seyir Defteri" };
interface Goal {
id: string;
title: string;
description: string;
status: "completed" | "in-progress" | "planned" | "paused";
progress: number;
category: string;
deadline?: string;
notes?: string;
}
const goals: Goal[] = [
{
id: "1",
title: "OSCP Sertifikası",
description: "Offensive Security Certified Professional sınavını geçmek",
status: "in-progress",
progress: 35,
category: "Sertifika",
deadline: "2026-12-31",
notes: "Active Directory modüllerine odaklanılıyor",
},
{
id: "2",
title: "denizbektas.com.tr Yayına Almak",
description: "Kişisel siteyi oluşturmak ve yayına almak",
status: "completed",
progress: 100,
category: "Proje",
},
{
id: "3",
title: "50 HTB Makinesi",
description: "HackTheBox'ta 50 makine çözmek",
status: "in-progress",
progress: 47,
category: "Pratik",
},
{
id: "4",
title: "Podcast Başlatmak",
description: "Türkçe siber güvenlik podcast'i yayınlamak",
status: "planned",
progress: 10,
category: "İçerik",
deadline: "2026-09-01",
},
{
id: "5",
title: "Red Team Araç Geliştirme",
description: "Kendi C2 implant'ımı yazmak (Rust ile)",
status: "paused",
progress: 15,
category: "Geliştirme",
},
{
id: "6",
title: "10 Infosec Yazısı",
description: "Kaliteli teknik yazılar yayınlamak",
status: "in-progress",
progress: 10,
category: "İçerik",
},
];
const statusConfig = {
completed: { label: "Tamamlandı", color: "#00d4aa", icon: "✓" },
"in-progress": { label: "Devam Ediyor", color: "#f59e0b", icon: "◉" },
planned: { label: "Planlandı", color: "#64748b", icon: "◎" },
paused: { label: "Durduruldu", color: "#ef4444", icon: "⏸" },
};
export default function SeyirDefteriPage() {
const byCategory = goals.reduce((acc, g) => {
if (!acc[g.category]) acc[g.category] = [];
acc[g.category].push(g);
return acc;
}, {} as Record<string, Goal[]>);
return (
<div style={{ maxWidth: "100%" }}>
<div className="page-title">Kaptanın Seyir Defteri</div>
<p style={{ fontSize: "0.8rem", color: "var(--text-muted)", marginBottom: "2rem" }}>
Hedeflerim ve ilerleme durumum
</p>
{/* Summary */}
<div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: "0.5rem", marginBottom: "2rem" }}>
{(["completed", "in-progress", "planned", "paused"] as const).map((s) => {
const count = goals.filter((g) => g.status === s).length;
const cfg = statusConfig[s];
return (
<div key={s} className="card" style={{ textAlign: "center", padding: "0.75rem" }}>
<div style={{ fontSize: "1.2rem", fontWeight: 700, color: cfg.color }}>{count}</div>
<div style={{ fontSize: "0.65rem", color: "var(--text-muted)", marginTop: "0.2rem" }}>{cfg.label}</div>
</div>
);
})}
</div>
{/* Goals by category */}
{Object.entries(byCategory).map(([cat, catGoals]) => (
<div key={cat} style={{ marginBottom: "1.5rem" }}>
<div className="section-header">{cat}</div>
<div style={{ display: "flex", flexDirection: "column", gap: "0.75rem" }}>
{catGoals.map((goal) => {
const cfg = statusConfig[goal.status];
return (
<div key={goal.id} className="card">
<div style={{ display: "flex", alignItems: "flex-start", justifyContent: "space-between", gap: "1rem", marginBottom: "0.4rem" }}>
<div>
<div style={{ display: "flex", alignItems: "center", gap: "0.4rem", marginBottom: "0.2rem" }}>
<span style={{ color: cfg.color, fontSize: "0.7rem" }}>{cfg.icon}</span>
<h3 style={{ fontSize: "0.9rem", fontWeight: 600, color: "var(--text)" }}>{goal.title}</h3>
</div>
<p style={{ fontSize: "0.78rem", color: "var(--text-muted)" }}>{goal.description}</p>
</div>
<span style={{ fontSize: "0.65rem", background: "var(--bg)", border: `1px solid ${cfg.color}`, color: cfg.color, padding: "0.15rem 0.4rem", borderRadius: "3px", flexShrink: 0 }}>
{cfg.label}
</span>
</div>
{/* Progress bar */}
<div style={{ marginTop: "0.75rem" }}>
<div style={{ display: "flex", justifyContent: "space-between", fontSize: "0.7rem", color: "var(--text-muted)", marginBottom: "0.25rem" }}>
<span>İlerleme</span>
<span style={{ color: cfg.color, fontWeight: 600 }}>{goal.progress}%</span>
</div>
<div style={{ height: "4px", background: "var(--bg)", borderRadius: "2px", overflow: "hidden" }}>
<div style={{ height: "100%", width: `${goal.progress}%`, background: cfg.color, borderRadius: "2px", transition: "width 0.3s" }} />
</div>
</div>
{(goal.deadline || goal.notes) && (
<div style={{ marginTop: "0.5rem", fontSize: "0.72rem", color: "var(--text-muted)", display: "flex", gap: "1rem", flexWrap: "wrap" }}>
{goal.deadline && <span>🗓 {new Date(goal.deadline).toLocaleDateString("tr-TR", { year: "numeric", month: "long" })}</span>}
{goal.notes && <span>📝 {goal.notes}</span>}
</div>
)}
</div>
);
})}
</div>
</div>
))}
</div>
);
}

71
app/sitemap.xml/route.ts Normal file
View File

@@ -0,0 +1,71 @@
import { NextResponse } from "next/server";
import { getAllPosts } from "@/lib/posts";
const SITE_URL = "https://denizbektas.com.tr";
const staticPages = [
{ url: "/", priority: "1.0", changefreq: "weekly" },
{ url: "/merhaba", priority: "0.8", changefreq: "monthly" },
{ url: "/hakkimda", priority: "0.8", changefreq: "monthly" },
{ url: "/su-anda", priority: "0.7", changefreq: "weekly" },
{ url: "/misyon", priority: "0.6", changefreq: "monthly" },
{ url: "/blog", priority: "0.9", changefreq: "weekly" },
{ url: "/infosec", priority: "0.9", changefreq: "weekly" },
{ url: "/notebook", priority: "0.8", changefreq: "weekly" },
{ url: "/seyir-defteri", priority: "0.7", changefreq: "weekly" },
{ url: "/faydali-linkler", priority: "0.7", changefreq: "monthly" },
{ url: "/roadmap", priority: "0.8", changefreq: "monthly" },
{ url: "/takim-cantam", priority: "0.6", changefreq: "monthly" },
{ url: "/hobilerim", priority: "0.5", changefreq: "monthly" },
{ url: "/fikirlerim", priority: "0.7", changefreq: "monthly" },
{ url: "/projeler", priority: "0.8", changefreq: "monthly" },
{ url: "/podcast", priority: "0.7", changefreq: "weekly" },
{ url: "/iletisim", priority: "0.6", changefreq: "monthly" },
{ url: "/ozgecmis", priority: "0.7", changefreq: "monthly" },
{ url: "/aktivite", priority: "0.6", changefreq: "daily" },
{ url: "/rss-beslemeleri", priority: "0.5", changefreq: "monthly" },
{ url: "/statboard", priority: "0.5", changefreq: "monthly" },
{ url: "/altyapi", priority: "0.5", changefreq: "monthly" },
{ url: "/tesekkurler", priority: "0.4", changefreq: "yearly" },
{ url: "/gizlilik", priority: "0.3", changefreq: "yearly" },
{ url: "/kullanim-kosullari", priority: "0.3", changefreq: "yearly" },
];
export async function GET() {
const posts = getAllPosts();
const now = new Date().toISOString().split("T")[0];
const staticUrls = staticPages
.map(
(p) => `
<url>
<loc>${SITE_URL}${p.url}</loc>
<lastmod>${now}</lastmod>
<changefreq>${p.changefreq}</changefreq>
<priority>${p.priority}</priority>
</url>`
)
.join("");
const postUrls = posts
.map(
(p) => `
<url>
<loc>${SITE_URL}/${p.category}/${p.slug}</loc>
<lastmod>${p.date}</lastmod>
<changefreq>monthly</changefreq>
<priority>0.8</priority>
</url>`
)
.join("");
const xml = `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
${staticUrls}
${postUrls}
</urlset>`;
return new NextResponse(xml, {
headers: { "Content-Type": "application/xml; charset=utf-8", "Cache-Control": "public, max-age=86400" },
});
}

79
app/statboard/page.tsx Normal file
View File

@@ -0,0 +1,79 @@
import type { Metadata } from "next";
export const metadata: Metadata = { title: "Statboard" };
const stats = [
{ label: "Blog Yazısı", value: "1", icon: "✍", unit: "yazı", desc: "Yayınlanmış blog yazıları" },
{ label: "Infosec Yazısı", value: "1", icon: "⚔", unit: "yazı", desc: "Teknik güvenlik yazıları" },
{ label: "Notebook Notu", value: "1", icon: "◎", unit: "not", desc: "Kısa düşünceler" },
{ label: "HTB Makinesi", value: "47", icon: "◆", unit: "makine", desc: "HackTheBox'ta çözülen makineler" },
{ label: "CTF Çözümü", value: "23", icon: "◈", unit: "flag", desc: "Yakalanan CTF bayrakları" },
{ label: "Satır Kod", value: "12.4k", icon: "▦", unit: "satır", desc: "Bu yıl yazılan kod satırı" },
{ label: "Çay", value: "∞", icon: "☕", unit: "bardak", desc: "Tüketilen çay miktarı" },
{ label: "Kahvesiz Gün", value: "0", icon: "◎", unit: "gün", desc: "Çünkü kahve olmadan olmaz" },
{ label: "Terminal Oturumu", value: "847", icon: "▶", unit: "oturum", desc: "Açılan terminal oturumları" },
{ label: "Git Commit", value: "234", icon: "◇", unit: "commit", desc: "Bu yıl yapılan commit'ler" },
{ label: "Gece Çalışması", value: "67", icon: "◑", unit: "gece", desc: "Gece 00:00 sonrası aktif gün" },
{ label: "VPN Bağlantısı", value: "365", icon: "⊘", unit: "gün", desc: "VPN açık gün sayısı" },
];
const milestones = [
{ date: "2026-04-03", event: "denizbektas.com.tr yayına alındı", icon: "🚀" },
{ date: "2026-03-15", event: "HTB'de 40. makine çözüldü", icon: "◆" },
{ date: "2026-02-01", event: "eJPT sertifikası alındı", icon: "🏆" },
{ date: "2025-12-25", event: "İlk CTF birinciliği", icon: "🥇" },
{ date: "2025-06-10", event: "İlk pentest projesi", icon: "⚔" },
];
export default function StatboardPage() {
return (
<div style={{ maxWidth: "100%" }}>
<div className="page-title">Statboard</div>
<p style={{ fontSize: "0.8rem", color: "var(--text-muted)", marginBottom: "2rem" }}>
Anlamsız ama eğlenceli istatistikler
</p>
{/* Main stats grid */}
<div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(180px, 1fr))", gap: "0.75rem", marginBottom: "2rem" }}>
{stats.map((stat) => (
<div key={stat.label} className="card" style={{ textAlign: "center", padding: "1rem" }}>
<div style={{ fontSize: "1.4rem", marginBottom: "0.3rem" }}>{stat.icon}</div>
<div style={{ fontSize: "1.5rem", fontWeight: 800, color: "var(--accent)", lineHeight: 1 }}>{stat.value}</div>
<div style={{ fontSize: "0.65rem", color: "var(--text-muted)", textTransform: "uppercase", letterSpacing: "0.06em", marginTop: "0.2rem" }}>{stat.unit}</div>
<div style={{ fontSize: "0.72rem", color: "var(--text)", marginTop: "0.4rem" }}>{stat.label}</div>
<div style={{ fontSize: "0.65rem", color: "var(--text-muted)", marginTop: "0.15rem" }}>{stat.desc}</div>
</div>
))}
</div>
{/* Milestones */}
<div className="section-header">Kilometre Taşları</div>
<div className="card">
<ul style={{ listStyle: "none", display: "flex", flexDirection: "column" }}>
{milestones.map((m, i) => (
<li
key={i}
style={{
display: "flex",
alignItems: "center",
gap: "1rem",
padding: "0.6rem 0",
borderBottom: i < milestones.length - 1 ? "1px solid var(--border)" : "none",
}}
>
<span style={{ fontSize: "1rem", flexShrink: 0 }}>{m.icon}</span>
<span style={{ flex: 1, fontSize: "0.85rem", color: "var(--text)" }}>{m.event}</span>
<span style={{ fontSize: "0.72rem", color: "var(--text-muted)", flexShrink: 0 }}>
{new Date(m.date).toLocaleDateString("tr-TR", { year: "numeric", month: "short", day: "numeric" })}
</span>
</li>
))}
</ul>
</div>
<div style={{ marginTop: "1rem", fontSize: "0.72rem", color: "var(--text-muted)", textAlign: "center" }}>
Veriler elle güncellenmektedir. Kesinlik garantisi verilmez. ¯\_()_/¯
</div>
</div>
);
}

62
app/su-anda/page.tsx Normal file
View File

@@ -0,0 +1,62 @@
import type { Metadata } from "next";
export const metadata: Metadata = { title: "Şu Anda" };
const lastUpdated = "2026-04-03";
export default function SuAndaPage() {
return (
<div style={{ maxWidth: "100%" }}>
<div className="page-title">Şu Anda</div>
<p style={{ fontSize: "0.8rem", color: "var(--text-muted)", marginBottom: "0.5rem" }}>
Şu anda nelerle ilgileniyorum bir /now sayfası
</p>
<p style={{ fontSize: "0.72rem", color: "var(--text-muted)", marginBottom: "2rem" }}>
Son güncelleme: {lastUpdated}
</p>
<div className="card prose" style={{ marginBottom: "1rem" }}>
<h2>Odak</h2>
<p>
Red team metodolojileri üzerine yoğunlaşıyorum. Özellikle Active Directory saldırı
vektörleri ve lateral movement teknikleri üzerine lab çalışmaları yapıyorum.
</p>
<h2>Okuma</h2>
<ul>
<li><strong>The Hacker Playbook 3</strong> Peter Kim</li>
<li><strong>Red Team Development and Operations</strong> Joe Vest</li>
<li><strong>Pentest.ws writeupları</strong> çeşitli yazarlar</li>
</ul>
<h2>Öğrenme</h2>
<ul>
<li>Active Directory güvenliği (BloodHound, Impacket)</li>
<li>C2 framework mimarisi (Havoc, Sliver)</li>
<li>Rust ile araç geliştirme</li>
</ul>
<h2>Hedefler</h2>
<ul>
<li>🎯 OSCP sınavına girmek</li>
<li>🎯 Bu siteyi canlıya almak </li>
<li>🎯 10 HTB makinesi çözmek</li>
<li>🎯 Podcast başlatmak</li>
</ul>
<h2>Dinleme</h2>
<p>Darksynth, Industrial, Dark Ambient çalışırken müzik olmazsa olmaz.</p>
<h2>İzleme</h2>
<ul>
<li>Mr. Robot (yeniden izleme)</li>
<li>Darknet Diaries Podcast</li>
</ul>
</div>
<div style={{ fontSize: "0.72rem", color: "var(--text-muted)", marginTop: "1rem" }}>
Bu sayfa <a href="https://nownownow.com" target="_blank" rel="noopener noreferrer">/now</a> hareketi ilhamıyla oluşturulmuştur.
</div>
</div>
);
}

138
app/takim-cantam/page.tsx Normal file
View File

@@ -0,0 +1,138 @@
import type { Metadata } from "next";
export const metadata: Metadata = { title: "Takım Çantam" };
const sections = [
{
title: "Donanım",
icon: "⊡",
items: [
{ name: "MacBook Pro M3", desc: "Ana geliştirme makinesi", badge: "primary" },
{ name: "Thinkpad X1 Carbon", desc: "Kali Linux dedicated lab makinesi", badge: "lab" },
{ name: "Raspberry Pi 4", desc: "Home lab server", badge: "server" },
{ name: "Alfa AWUS036ACM", desc: "WiFi pentesting adaptör", badge: "tool" },
{ name: "HakCat USB Nugget", desc: "BadUSB payload testi", badge: "tool" },
{ name: "Flipper Zero", desc: "RF/NFC/IR/Sub-GHz multi-tool", badge: "tool" },
],
},
{
title: "İşletim Sistemleri",
icon: "◈",
items: [
{ name: "Kali Linux", desc: "Ana pentest OS — rolling release", badge: "primary" },
{ name: "macOS Sequoia", desc: "Günlük sürücü", badge: "primary" },
{ name: "ParrotOS", desc: "Alternatif güvenlik distrosu", badge: "secondary" },
{ name: "Windows 11", desc: "Lab için VM", badge: "vm" },
],
},
{
title: "Güvenlik Araçları",
icon: "⚔",
items: [
{ name: "Burp Suite Pro", desc: "Web uygulama test aracı", badge: "pro" },
{ name: "Nmap", desc: "Ağ keşif ve tarama", badge: "oss" },
{ name: "Metasploit Framework", desc: "Exploit framework", badge: "oss" },
{ name: "Cobalt Strike", desc: "Red team C2 (lab)", badge: "pro" },
{ name: "BloodHound", desc: "AD attack path analizi", badge: "oss" },
{ name: "Impacket", desc: "Python ağ protokol kütüphanesi", badge: "oss" },
{ name: "Ghidra", desc: "Reverse engineering", badge: "oss" },
{ name: "Wireshark", desc: "Ağ protokol analizi", badge: "oss" },
{ name: "Hashcat", desc: "GPU hızlandırmalı şifre kırma", badge: "oss" },
{ name: "John the Ripper", desc: "Şifre kırma aracı", badge: "oss" },
{ name: "SQLMap", desc: "Otomatik SQL injection", badge: "oss" },
{ name: "Nuclei", desc: "Hızlı güvenlik tarayıcı", badge: "oss" },
],
},
{
title: "Geliştirme",
icon: "◎",
items: [
{ name: "Neovim", desc: "Birincil editör (LazyVim)", badge: "primary" },
{ name: "VS Code", desc: "İkincil editör", badge: "secondary" },
{ name: "WezTerm", desc: "Terminal emülatör", badge: "primary" },
{ name: "tmux", desc: "Terminal multiplexer", badge: "tool" },
{ name: "Fish Shell", desc: "Interaktif shell", badge: "tool" },
{ name: "Git", desc: "Versiyon kontrolü", badge: "tool" },
{ name: "Docker", desc: "Container ortamları", badge: "tool" },
],
},
{
title: "Programlama Dilleri",
icon: "▦",
items: [
{ name: "Python", desc: "Script, otomasyon, exploit geliştirme", badge: "primary" },
{ name: "Bash", desc: "Shell scripting", badge: "primary" },
{ name: "Rust", desc: "Öğreniyorum — araç geliştirme için", badge: "learning" },
{ name: "C/C++", desc: "Exploit geliştirme, düşük seviye", badge: "secondary" },
{ name: "PowerShell", desc: "Windows otomasyon", badge: "secondary" },
{ name: "JavaScript/TypeScript", desc: "Bu site!", badge: "secondary" },
],
},
{
title: "Servisler & Abonelikler",
icon: "◆",
items: [
{ name: "HackTheBox VIP", desc: "Lab makineleri ve challenge'lar", badge: "sub" },
{ name: "1Password", desc: "Şifre yöneticisi", badge: "sub" },
{ name: "Mullvad VPN", desc: "Gizlilik odaklı VPN", badge: "sub" },
{ name: "Proton Mail", desc: "Şifreli e-posta", badge: "sub" },
],
},
];
const badgeColors: Record<string, string> = {
primary: "#00d4aa",
secondary: "#64748b",
pro: "#f59e0b",
oss: "#22c55e",
lab: "#7c6af7",
server: "#3b82f6",
vm: "#64748b",
tool: "#ef4444",
sub: "#ec4899",
learning: "#f97316",
};
export default function TakimCantamPage() {
return (
<div style={{ maxWidth: "100%" }}>
<div className="page-title">Takım Çantam</div>
<p style={{ fontSize: "0.8rem", color: "var(--text-muted)", marginBottom: "2rem" }}>
Kullandığım cihazlar, araçlar, yazılımlar ve servisler
</p>
<div style={{ display: "flex", flexDirection: "column", gap: "2rem" }}>
{sections.map((section) => (
<div key={section.title}>
<div className="section-header">
<span style={{ color: "var(--accent)", marginRight: "0.4rem" }}>{section.icon}</span>
{section.title}
</div>
<div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(240px, 1fr))", gap: "0.5rem" }}>
{section.items.map((item) => (
<div key={item.name} className="card" style={{ padding: "0.75rem 1rem" }}>
<div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: "0.2rem" }}>
<span style={{ fontSize: "0.85rem", fontWeight: 600, color: "var(--text)" }}>{item.name}</span>
<span style={{
fontSize: "0.55rem",
padding: "0.1rem 0.35rem",
borderRadius: "2px",
fontWeight: 700,
letterSpacing: "0.06em",
textTransform: "uppercase",
color: badgeColors[item.badge] || "var(--text-muted)",
border: `1px solid ${badgeColors[item.badge] || "var(--border)"}`,
}}>
{item.badge}
</span>
</div>
<p style={{ fontSize: "0.75rem", color: "var(--text-muted)", margin: 0 }}>{item.desc}</p>
</div>
))}
</div>
</div>
))}
</div>
</div>
);
}

52
app/tesekkurler/page.tsx Normal file
View File

@@ -0,0 +1,52 @@
import type { Metadata } from "next";
export const metadata: Metadata = { title: "Teşekkürler" };
export default function TesekkurlerPage() {
return (
<div style={{ maxWidth: "100%" }}>
<div className="page-title">Teşekkürler</div>
<p style={{ fontSize: "0.8rem", color: "var(--text-muted)", marginBottom: "2rem" }}>
Sitede ve kariyerimde emeği geçenlere
</p>
<div className="card prose" style={{ marginBottom: "1rem" }}>
<h2>İnsanlar</h2>
<p>
Bana siber güvenliği öğreten, mentorluk eden ve bu yolculukta yanımda olan herkese.
İsim vermek yerine biliyorlar. 🤝
</p>
<h2>İçerik Üreticileri</h2>
<ul>
<li><strong>IppSec</strong> HTB makinelerini anlatan YouTube videoları, öğrenmenin en iyi yolu</li>
<li><strong>0xdf</strong> Detaylı ve ıklayıcı writeupları</li>
<li><strong>Darknet Diaries (Jack Rhysider)</strong> Siber suç hikayelerini mükemmel anlatan podcast</li>
<li><strong>LiveOverflow</strong> Binary exploitation ve CTF içerikleri</li>
<li><strong>John Hammond</strong> CTF çözümleri ve güvenlik araştırmaları</li>
</ul>
<h2>Topluluklar</h2>
<ul>
<li><strong>HackTheBox Community</strong> Forumlarda yardımcı olan herkese</li>
<li><strong>Türk infosec topluluğu</strong> Discord, Twitter ve meetup'larda tanıştığım herkes</li>
<li><strong>CTF ekipleri</strong> Beraber oynadığımız turnuvalarda takım arkadaşlarım</li>
</ul>
<h2>ık Kaynak</h2>
<p>
Bu site ve kariyer yolculuğumda kullandığım tüm ık kaynak araçların geliştiricilerine.
Özellikle: Next.js, Kali Linux, Metasploit, Burp Suite Community Edition, Ghidra, Nmap...
</p>
<p>
ık kaynak olmadan bu alan bu kadar demokratik olamazdı.
</p>
<h2>Aileme</h2>
<p>
Gece yarıları terminalde oturup garip şeyler yaptığımda soru sormayan aileme.
</p>
</div>
</div>
);
}

285
components/Navigation.tsx Normal file
View File

@@ -0,0 +1,285 @@
'use client';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
import { useState } from 'react';
import { useTheme } from './ThemeProvider';
const navGroups = [
{
label: 'Ana',
items: [
{ href: '/', label: 'Anasayfa', icon: '~' },
{ href: '/merhaba', label: 'Merhaba', icon: '>' },
{ href: '/hakkimda', label: 'Hakkımda', icon: '@' },
{ href: '/su-anda', label: 'Şu Anda', icon: '◉' },
{ href: '/misyon', label: 'Misyon', icon: '⚑' },
],
},
{
label: 'İçerik',
items: [
{ href: '/blog', label: 'Personal Blog', icon: '✍' },
{ href: '/notebook', label: 'Notebook', icon: '◎' },
{ href: '/infosec', label: 'Infosec Posts', icon: '⚔' },
{ href: '/seyir-defteri', label: 'Seyir Defteri', icon: '⚓' },
{ href: '/projeler', label: 'Projeler', icon: '◈' },
{ href: '/podcast', label: 'Podcast', icon: '◉' },
],
},
{
label: 'Koleksiyon',
items: [
{ href: '/faydali-linkler', label: 'Faydalı Linkler', icon: '⊞' },
{ href: '/roadmap', label: 'Roadmap', icon: '◆' },
{ href: '/takim-cantam', label: 'Takım Çantam', icon: '⊡' },
{ href: '/hobilerim', label: 'Hobilerim', icon: '♦' },
{ href: '/fikirlerim', label: 'Fikirlerim', icon: '◇' },
],
},
{
label: 'Bilgi',
items: [
{ href: '/iletisim', label: 'İletişim', icon: '✉' },
{ href: '/ozgecmis', label: 'Özgeçmiş', icon: '▤' },
{ href: '/aktivite', label: 'Aktivite', icon: '▶' },
{ href: '/rss-beslemeleri', label: 'RSS Beslemeleri', icon: '◈' },
{ href: '/statboard', label: 'Statboard', icon: '▦' },
{ href: '/altyapi', label: 'Altyapı', icon: '⊟' },
{ href: '/tesekkurler', label: 'Teşekkürler', icon: '♡' },
],
},
{
label: 'Meta',
items: [
{ href: '/gizlilik', label: 'Gizlilik', icon: '⊘' },
{ href: '/kullanim-kosullari', label: 'Kullanım Koşulları', icon: '⊘' },
{ href: '/humans.txt', label: 'humans.txt', icon: '▸', external: true },
{ href: '/security.txt', label: 'security.txt', icon: '▸', external: true },
{ href: '/public.pgp', label: 'public.pgp', icon: '▸', external: true },
],
},
{
label: 'Harici',
items: [
{ href: '/mastodon', label: 'Mastodon', icon: '⊕', external: true },
{ href: 'mailto:info@denizbektas.com.tr', label: 'E-Mail', icon: '✉', external: true },
],
},
];
export default function Navigation() {
const pathname = usePathname();
const { theme, toggle } = useTheme();
const [mobileOpen, setMobileOpen] = useState(false);
const isActive = (href: string) => {
if (href === '/') return pathname === '/';
return pathname.startsWith(href);
};
const sidebarContent = (
<nav style={{ display: 'flex', flexDirection: 'column', gap: '1.25rem' }}>
{navGroups.map((group) => (
<div key={group.label}>
<div className="section-header">{group.label}</div>
<ul style={{ listStyle: 'none', display: 'flex', flexDirection: 'column', gap: '1px' }}>
{group.items.map((item) => (
<li key={item.href}>
{item.external && item.href.startsWith('mailto:') ? (
<a
href={item.href}
style={{
display: 'flex',
alignItems: 'center',
gap: '0.5rem',
padding: '0.3rem 0.5rem',
borderRadius: '4px',
fontSize: '0.93rem',
color: 'var(--text-muted)',
transition: 'all 0.15s',
}}
>
<span style={{ color: 'var(--accent)', width: '1.1rem', flexShrink: 0, fontSize: '0.82rem' }}>{item.icon}</span>
{item.label}
</a>
) : item.external && !item.href.startsWith('/') ? (
<a
href={item.href}
target="_blank"
rel="noopener noreferrer"
style={{
display: 'flex',
alignItems: 'center',
gap: '0.5rem',
padding: '0.3rem 0.5rem',
borderRadius: '4px',
fontSize: '0.93rem',
color: 'var(--text-muted)',
}}
>
<span style={{ color: 'var(--accent)', width: '1.1rem', flexShrink: 0, fontSize: '0.82rem' }}>{item.icon}</span>
{item.label}
<span style={{ marginLeft: 'auto', fontSize: '0.7rem', opacity: 0.5 }}></span>
</a>
) : (
<Link
href={item.href}
target={item.external ? '_blank' : undefined}
onClick={() => setMobileOpen(false)}
style={{
display: 'flex',
alignItems: 'center',
gap: '0.5rem',
padding: '0.35rem 0.5rem',
borderRadius: '4px',
fontSize: '0.93rem',
color: isActive(item.href) ? 'var(--accent)' : 'var(--text-muted)',
background: isActive(item.href) ? 'var(--tag-bg)' : 'transparent',
fontWeight: isActive(item.href) ? '600' : '400',
transition: 'all 0.15s',
opacity: 1,
}}
>
<span style={{ color: 'var(--accent)', width: '1.1rem', flexShrink: 0, fontSize: '0.82rem' }}>{item.icon}</span>
{item.label}
{item.external && <span style={{ marginLeft: 'auto', fontSize: '0.7rem', opacity: 0.5 }}></span>}
</Link>
)}
</li>
))}
</ul>
</div>
))}
</nav>
);
return (
<>
{/* Desktop Sidebar */}
<aside
className="desktop-sidebar"
style={{
width: '272px',
flexShrink: 0,
background: 'var(--sidebar-bg)',
borderRight: '1px solid var(--border)',
height: '100vh',
position: 'sticky',
top: 0,
overflowY: 'auto',
display: 'flex',
flexDirection: 'column',
}}
>
{/* Logo */}
<div style={{ padding: '1.25rem 1rem', borderBottom: '1px solid var(--border)' }}>
<Link href="/" style={{ display: 'block', color: 'var(--accent)', fontWeight: '800', fontSize: '1.1rem', letterSpacing: '-0.02em' }}>
denizbektas<span style={{ color: 'var(--text-muted)', fontWeight: 400 }}>.com.tr</span>
</Link>
<div style={{ fontSize: '0.78rem', color: 'var(--text-muted)', marginTop: '0.25rem' }}>siber güvenlik uzmanı</div>
</div>
{/* Theme Toggle */}
<div style={{ padding: '0.75rem 1rem', borderBottom: '1px solid var(--border)' }}>
<button
onClick={toggle}
style={{
display: 'flex',
alignItems: 'center',
gap: '0.5rem',
fontSize: '0.88rem',
color: 'var(--text-muted)',
background: 'none',
border: 'none',
cursor: 'pointer',
padding: '0.35rem 0.5rem',
borderRadius: '4px',
width: '100%',
fontFamily: 'inherit',
transition: 'color 0.15s',
}}
>
<span style={{ fontSize: '0.9rem' }}>{theme === 'dark' ? '☀' : '◑'}</span>
{theme === 'dark' ? 'Light Mode' : 'Dark Mode'}
</button>
</div>
{/* Nav */}
<div style={{ padding: '1rem', flex: 1 }}>
{sidebarContent}
</div>
{/* Footer */}
<div style={{ padding: '0.75rem 1rem', borderTop: '1px solid var(--border)', fontSize: '0.6rem', color: 'var(--text-muted)' }}>
<div>© 2026 denizbektas</div>
<div style={{ marginTop: '0.2rem', color: 'var(--accent)', opacity: 0.6 }}>
<span className="blink"></span>
</div>
</div>
</aside>
{/* Mobile Header */}
<header
className="mobile-header"
style={{
display: 'none',
position: 'fixed',
top: 0,
left: 0,
right: 0,
height: '52px',
background: 'var(--header-bg)',
backdropFilter: 'blur(8px)',
borderBottom: '1px solid var(--border)',
zIndex: 100,
alignItems: 'center',
justifyContent: 'space-between',
padding: '0 1rem',
}}
>
<Link href="/" style={{ color: 'var(--accent)', fontWeight: '800', fontSize: '0.95rem' }}>
denizbektas<span style={{ color: 'var(--text-muted)', fontWeight: 400 }}>.dev</span>
</Link>
<div style={{ display: 'flex', alignItems: 'center', gap: '0.75rem' }}>
<button onClick={toggle} style={{ background: 'none', border: 'none', cursor: 'pointer', fontSize: '1rem', color: 'var(--text-muted)' }}>
{theme === 'dark' ? '☀' : '◑'}
</button>
<button
onClick={() => setMobileOpen(!mobileOpen)}
style={{ background: 'none', border: 'none', cursor: 'pointer', color: 'var(--text)', fontSize: '1.2rem', fontFamily: 'inherit' }}
>
{mobileOpen ? '✕' : '☰'}
</button>
</div>
</header>
{/* Mobile Nav Overlay */}
{mobileOpen && (
<div
style={{
position: 'fixed',
top: '52px',
left: 0,
right: 0,
bottom: 0,
background: 'var(--sidebar-bg)',
zIndex: 99,
overflowY: 'auto',
padding: '1rem',
borderTop: '1px solid var(--border)',
}}
>
{sidebarContent}
</div>
)}
<style>{`
@media (max-width: 768px) {
.desktop-sidebar { display: none !important; }
.mobile-header { display: flex !important; }
}
`}</style>
</>
);
}

View File

@@ -0,0 +1,36 @@
'use client';
import { createContext, useContext, useEffect, useState } from 'react';
type Theme = 'dark' | 'light';
const ThemeContext = createContext<{
theme: Theme;
toggle: () => void;
}>({ theme: 'dark', toggle: () => {} });
export function ThemeProvider({ children }: { children: React.ReactNode }) {
const [theme, setTheme] = useState<Theme>('dark');
useEffect(() => {
const stored = localStorage.getItem('theme') as Theme | null;
const initial = stored || 'dark';
setTheme(initial);
document.documentElement.setAttribute('data-theme', initial);
}, []);
const toggle = () => {
const next = theme === 'dark' ? 'light' : 'dark';
setTheme(next);
localStorage.setItem('theme', next);
document.documentElement.setAttribute('data-theme', next);
};
return (
<ThemeContext.Provider value={{ theme, toggle }}>
{children}
</ThemeContext.Provider>
);
}
export const useTheme = () => useContext(ThemeContext);

30
content/activity.json Normal file
View File

@@ -0,0 +1,30 @@
[
{
"id": "1",
"timestamp": "2026-04-03T10:00:00.000Z",
"type": "system",
"message": "Site yayına alındı. denizbektas.com.tr hayata geçti.",
"link": "/"
},
{
"id": "2",
"timestamp": "2026-04-03T10:05:00.000Z",
"type": "post",
"message": "İlk blog yazısı yayınlandı: Neden Siber Güvenlik?",
"link": "/blog/neden-siber-guvenlik"
},
{
"id": "3",
"timestamp": "2026-04-03T10:10:00.000Z",
"type": "infosec",
"message": "İlk infosec yazısı: Nmap ile Ağ Keşfi",
"link": "/infosec/nmap-ag-kesfi"
},
{
"id": "4",
"timestamp": "2026-04-03T10:15:00.000Z",
"type": "notebook",
"message": "Notebook'a ilk not eklendi.",
"link": "/notebook/ilk-not"
}
]

View File

@@ -0,0 +1,26 @@
---
title: "Neden Siber Güvenlik?"
date: "2026-04-01"
excerpt: "Siber güvenliğe nasıl başladım, neden bu alanı seçtim ve bu yolculukta neler öğrendim."
tags: ["kişisel", "kariyer", "siber güvenlik"]
---
# Neden Siber Güvenlik?
Her şey merakla başladı. Çocukluğumda bilgisayarların *nasıl çalıştığını* anlamak istiyordum — sadece kullanmak değil, içini görmek.
## İlk Adımlar
İlk kez bir sisteme "girildiğinde" ne hissedildiğini anlamak için yıllarca kafamı duvara vurdum. CTF yarışmaları, HackTheBox, TryHackMe — hepsini denedim.
## Bu Yolculuk
Red team operasyonları, offensive security, pentest... Bu kelimelerin arkasında gerçek bir disiplin var. Ve bu disiplin beni her gün daha fazla çekiyor.
> "The quieter you become, the more you are able to hear." — Kali Linux motto
## Sonuç
Siber güvenlik bir meslek değil, bir yaşam biçimi. Sürekli öğrenme, sürekli adaptasyon, sürekli sorgulama.
Bu site de o yolculuğun bir parçası.

View File

@@ -0,0 +1,82 @@
---
title: "Nmap ile Ağ Keşfi"
date: "2026-04-02"
excerpt: "Nmap'in temel ve ileri düzey kullanımı, port tarama teknikleri ve pratik örnekler."
tags: ["nmap", "reconnaissance", "network", "tools"]
---
# Nmap ile Ağ Keşfi
Nmap (Network Mapper), ağ keşfi ve güvenlik denetimi için kullanılan açık kaynaklı bir araçtır. Her pentest operasyonunun ilk adımı genellikle Nmap ile başlar.
## Temel Kullanım
```bash
# Basit port tarama
nmap 192.168.1.1
# Belirli portları tara
nmap -p 22,80,443 192.168.1.1
# Tüm portları tara
nmap -p- 192.168.1.1
```
## SYN Scan (Stealth Scan)
```bash
# Root yetkisi gerektirir
sudo nmap -sS 192.168.1.1
```
SYN scan, tam TCP bağlantısı kurmadan portların açık olup olmadığını tespit eder. Daha az iz bırakır.
## Servis ve Versiyon Tespiti
```bash
nmap -sV -sC 192.168.1.1
```
## OS Fingerprinting
```bash
sudo nmap -O 192.168.1.1
```
## Agresif Tarama
```bash
sudo nmap -A 192.168.1.1
```
`-A` bayrağı; OS tespiti, versiyon tespiti, script tarama ve traceroute'u birleştirir.
## NSE Scripts
```bash
# Tüm scriptleri listele
ls /usr/share/nmap/scripts/
# Belirli bir script çalıştır
nmap --script=http-title 192.168.1.1
# Vuln kategorisi
nmap --script=vuln 192.168.1.1
```
## Pratik Örnekler
```bash
# Web sunucu keşfi
nmap -p 80,443,8080,8443 --open 192.168.1.0/24
# Hızlı subnet tarama
nmap -T4 -F 192.168.1.0/24
# XML çıktısı
nmap -oX scan.xml 192.168.1.1
```
## Sonuç
Nmap, her güvenlik uzmanının toolbox'ında olması gereken temel bir araçtır. Authorization olmadan kullanmak yasadışıdır — her zaman izinli sistemlerde test edin.

View File

@@ -0,0 +1,12 @@
---
title: "İlk Not"
date: "2026-04-03"
excerpt: "Bu notebook'un ilk notu. Aklımdan geçen şeyleri buraya yazacağım."
tags: ["düşünce"]
---
Bir şeyi öğrenmenin en iyi yolu onu başkasına anlatmaktır.
Bu notebook tam da bu amaçla var — anlık düşünceler, bağlantısız notlar, kafamdan geçen şeyler.
Twitter gibi ama daha az gürültü, daha çok sinyal.

30
lib/activity.ts Normal file
View File

@@ -0,0 +1,30 @@
import fs from 'fs';
import path from 'path';
export interface ActivityEntry {
id: string;
timestamp: string;
type: 'post' | 'notebook' | 'infosec' | 'project' | 'link' | 'update' | 'system';
message: string;
link?: string;
}
const activityFile = path.join(process.cwd(), 'content', 'activity.json');
export function getActivity(): ActivityEntry[] {
if (!fs.existsSync(activityFile)) return [];
const raw = fs.readFileSync(activityFile, 'utf-8');
return JSON.parse(raw);
}
export function addActivity(entry: Omit<ActivityEntry, 'id' | 'timestamp'>) {
const entries = getActivity();
const newEntry: ActivityEntry = {
id: Date.now().toString(),
timestamp: new Date().toISOString(),
...entry,
};
entries.unshift(newEntry);
fs.writeFileSync(activityFile, JSON.stringify(entries.slice(0, 500), null, 2));
return newEntry;
}

71
lib/posts.ts Normal file
View File

@@ -0,0 +1,71 @@
import fs from 'fs';
import path from 'path';
import matter from 'gray-matter';
import { remark } from 'remark';
import html from 'remark-html';
const contentDir = path.join(process.cwd(), 'content');
export interface Post {
slug: string;
title: string;
date: string;
excerpt: string;
tags: string[];
content?: string;
category: 'blog' | 'notebook' | 'infosec';
}
export function getPosts(category: 'blog' | 'notebook' | 'infosec'): Post[] {
const dir = path.join(contentDir, category);
if (!fs.existsSync(dir)) return [];
const files = fs.readdirSync(dir).filter((f) => f.endsWith('.md'));
return files
.map((filename) => {
const slug = filename.replace('.md', '');
const raw = fs.readFileSync(path.join(dir, filename), 'utf-8');
const { data } = matter(raw);
return {
slug,
title: data.title || slug,
date: data.date || '2024-01-01',
excerpt: data.excerpt || '',
tags: data.tags || [],
category,
};
})
.sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime());
}
export async function getPost(
category: 'blog' | 'notebook' | 'infosec',
slug: string
): Promise<Post | null> {
const filePath = path.join(contentDir, category, `${slug}.md`);
if (!fs.existsSync(filePath)) return null;
const raw = fs.readFileSync(filePath, 'utf-8');
const { data, content } = matter(raw);
const processed = await remark().use(html).process(content);
return {
slug,
title: data.title || slug,
date: data.date || '2024-01-01',
excerpt: data.excerpt || '',
tags: data.tags || [],
content: processed.toString(),
category,
};
}
export function getAllPosts(): Post[] {
return [
...getPosts('blog'),
...getPosts('infosec'),
...getPosts('notebook'),
].sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime());
}

1155
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -9,9 +9,15 @@
"lint": "eslint"
},
"dependencies": {
"date-fns": "^4.1.0",
"gray-matter": "^4.0.3",
"lucide-react": "^1.7.0",
"next": "16.2.2",
"next-themes": "^0.4.6",
"react": "19.2.4",
"react-dom": "19.2.4"
"react-dom": "19.2.4",
"remark": "^15.0.1",
"remark-html": "^16.0.1"
},
"devDependencies": {
"@tailwindcss/postcss": "^4",