Skip to content

Repository files navigation

ferhattufekci.github.io

🇬🇧 English | 🇹🇷 Türkçe


English

Personal portfolio website of Ferhat Tüfekçi.

Live: https://ferhattufekci.github.io

Tech Stack

  • HTML5 / CSS3 / JavaScript
  • jQuery + Shuffle.js (portfolio filtering)
  • GitHub Actions (Medium article sync + GitHub repo sync)
  • GitHub Pages (static hosting)

Project Structure

.
├── index.html                  # Single-page portfolio (partially auto-generated,
│                                #   see "SEO / AI Discoverability" below)
├── css/                        # Stylesheets
├── js/                         # Client-side scripts
├── images/                     # Images and assets
├── fonts/                      # Local fonts & icons
├── data/
│   ├── medium-systems.json     # Auto-generated by GitHub Actions
│   ├── medium-test.json
│   ├── medium-software.json
│   ├── medium-all.json
│   ├── meta.json
│   ├── github-repos.json       # Auto-generated by GitHub Actions
│   ├── github-starred.json     # Auto-generated by GitHub Actions
│   └── github-meta.json
├── scripts/
│   ├── fetch-medium.js         # Medium RSS fetcher
│   ├── fetch-github.js         # GitHub repos & stars fetcher
│   ├── build-static-seo.js     # Regenerates crawler-visible fallback
│   │                            #   content in index.html + llms.txt
│   └── package.json
├── .github/workflows/
│   ├── fetch-medium.yml        # Runs every 6 hours
│   └── fetch-github.yml        # Runs every Monday 03:00 UTC
├── FerhatTufekci_CV.pdf
├── ads.txt
├── robots.txt
├── sitemap.xml
├── llms.txt                    # Plain-text index for LLM/AI answer engines
└── BingSiteAuth.xml

Pages

Page Description
About Me Hero section with photo, title rotation, and "Why Work With Me?"
Resume Full CV as a web page — Summary, Top Skills, Languages, Education, Experience, Skills & Toolset, and Certifications
Blog Medium articles with language (EN/TR) and category filters
Projects GitHub repositories with category filters, pinned repos, and starred section
Contact Phone, email, Calendly interview scheduler, and links

Blog — Medium Auto-Sync

Articles are automatically fetched from Medium every 6 hours via GitHub Actions.

How it works:

  1. fetch-medium.js reads https://medium.com/feed/@ferhattufekci
  2. Category is detected automatically from RSS tags (systems / test / software)
  3. Language is detected automatically from title (Turkish characters → tr, otherwise en)
  4. Articles are saved to data/medium-*.json
  5. Browser reads these JSON files — no CORS issues

To exclude an article from the site:
Add its hex ID (last segment of the Medium URL) to the EXCLUDE array in scripts/fetch-medium.js.

No manual steps needed when publishing a new article on Medium.

Blog Language & Category Filters

The Blog section supports two independent filters:

Filter Options
Language All / 🇬🇧 EN / 🇹🇷 TR
Category All / Systems Engineering & Business Analysis / Test Engineering / Software Engineering

Projects — GitHub Auto-Sync

Repositories are automatically fetched from GitHub every Monday via GitHub Actions.

How it works:

  1. fetch-github.js calls GET /users/ferhattufekci/repos (REST API)
  2. Pinned repos are fetched via GitHub GraphQL API
  3. All languages per repo are fetched via GET /repos/{owner}/{repo}/languages
  4. Starred repos are fetched via GET /users/ferhattufekci/starred
  5. Category is detected automatically from repo name, description, and topics
  6. Results are saved to data/github-repos.json, data/github-starred.json, data/github-meta.json

Projects page sections:

Section Description
📌 PINNED Repos pinned on GitHub profile
📂 ALL REPOSITORIES All public repos, sorted by stars
⭐ STARRED Repos starred by Ferhat — resources he finds valuable (first 20 shown, expandable)

Category filter applies to PINNED and ALL REPOSITORIES sections.
Label updates dynamically to show the selected filter name.

To exclude a repo from the site:
Add the repo name to the EXCLUDE set in scripts/fetch-github.js.

No manual steps needed when creating or updating a repository.

SEO / AI Discoverability (GEO & AEO)

The Blog and Projects sections are populated client-side via fetch(), which Googlebot renders but many AI answer-engine crawlers (GPTBot, PerplexityBot, and others) don't — they read raw HTML only. Several things exist specifically to make this site's content visible to those crawlers too:

What Where Purpose
<noscript> fallback index.html, inside the Projects and Blog subpages Real titles/links/descriptions in the raw HTML for crawlers that don't execute JavaScript. Invisible to normal browsers with JS enabled — no visual or duplicate-content impact.
llms.txt site root Plain-text index (the emerging llms.txt convention) summarizing who this site is about, its core pages, and current articles/projects — meant to be fetched directly by LLM-based answer engines.
scripts/build-static-seo.js scripts/ Regenerates both of the above from data/github-repos.json and data/medium-all.json, so they can't go stale. Also bumps sitemap.xml's <lastmod>, but only on runs where it actually changed something.
Person.knowsAbout JSON-LD in index.html <head> Topical signals for search/AI, drawn from the existing <meta name="keywords"> list.
AI crawler allowlist robots.txt Explicitly lists GPTBot, ClaudeBot, PerplexityBot, Google-Extended, and others. Behavior is unchanged (the wildcard Allow: / already covered them) — this documents the opt-in.

build-static-seo.js runs automatically as a step in both fetch-github.yml and fetch-medium.yml, right after the data fetch, so the fallback content and llms.txt stay in sync with real data on every scheduled sync. It's idempotent — re-running it with unchanged data produces no diff, so it never creates empty commits.

To regenerate manually:

node scripts/build-static-seo.js

Run Locally

# VS Code Live Server (recommended)
# Right-click index.html → Open with Live Server

# Or Python
python3 -m http.server 8000

License

Published for portfolio and demonstration purposes.
All personal content, articles, images, and branding are the intellectual property of Ferhat Tüfekçi.
Any commercial use, redistribution, or derivative work requires prior written permission.

Author

Author LinkedIn Medium


Türkçe

Ferhat Tüfekçi'nin kişisel portföy web sitesi.

Canlı: https://ferhattufekci.github.io

Teknoloji Yığını

  • HTML5 / CSS3 / JavaScript
  • jQuery + Shuffle.js (portföy filtreleme)
  • GitHub Actions (Medium makale senkronizasyonu + GitHub repo senkronizasyonu)
  • GitHub Pages (statik barındırma)

Proje Yapısı

.
├── index.html                  # Tek sayfalık portföy (kısmen otomatik üretilir,
│                                #   bkz. aşağıdaki "SEO / AI Keşfedilebilirliği")
├── css/                        # Stil dosyaları
├── js/                         # İstemci tarafı betikler
├── images/                     # Görseller ve kaynaklar
├── fonts/                      # Yerel fontlar ve ikonlar
├── data/
│   ├── medium-systems.json     # GitHub Actions tarafından otomatik oluşturulur
│   ├── medium-test.json
│   ├── medium-software.json
│   ├── medium-all.json
│   ├── meta.json
│   ├── github-repos.json       # GitHub Actions tarafından otomatik oluşturulur
│   ├── github-starred.json     # GitHub Actions tarafından otomatik oluşturulur
│   └── github-meta.json
├── scripts/
│   ├── fetch-medium.js         # Medium RSS çekici
│   ├── fetch-github.js         # GitHub repo ve yıldız çekici
│   ├── build-static-seo.js     # index.html + llms.txt içindeki crawler'a
│   │                            #   özel yedek içeriği yeniden üretir
│   └── package.json
├── .github/workflows/
│   ├── fetch-medium.yml        # Her 6 saatte bir çalışır
│   └── fetch-github.yml        # Her Pazartesi 03:00 UTC'de çalışır
├── FerhatTufekci_CV.pdf
├── ads.txt
├── robots.txt
├── sitemap.xml
├── llms.txt                    # LLM/AI cevap motorları için düz metin özeti
└── BingSiteAuth.xml

Sayfalar

Sayfa Açıklama
About Me Fotoğraf, dönen başlık ve "Why Work With Me?" bölümü
Resume Tam özgeçmiş, web sayfası olarak — Summary, Top Skills, Languages, Education, Experience, Skills & Toolset ve Certifications
Blog Medium makaleleri — dil (EN/TR) ve kategori filtreleriyle
Projects GitHub repoları — kategori filtresi, sabitlenmiş repolar ve yıldızlı repolar
Contact Telefon, e-posta, Calendly mülakat planlayıcı ve bağlantılar

Blog — Medium Otomatik Senkronizasyonu

Makaleler, GitHub Actions aracılığıyla her 6 saatte bir Medium'dan otomatik olarak çekilir.

Nasıl çalışır:

  1. fetch-medium.js, https://medium.com/feed/@ferhattufekci adresini okur
  2. Kategori, RSS tag'lerinden otomatik tespit edilir (systems / test / software)
  3. Dil, başlıktaki Türkçe karakterlerden otomatik tespit edilir (Türkçe karakter → tr, aksi halde en)
  4. Makaleler data/medium-*.json dosyalarına kaydedilir
  5. Tarayıcı bu JSON dosyalarını okur — CORS sorunu yok

Bir makaleyi siteden gizlemek için:
scripts/fetch-medium.js dosyasındaki EXCLUDE dizisine Medium URL'sinin sonundaki hex ID'yi ekle.

Medium'da yeni makale yayınlandığında hiçbir manuel adım gerekmez.

Blog Dil ve Kategori Filtreleri

Blog bölümü iki bağımsız filtre destekler:

Filtre Seçenekler
Dil Tümü / 🇬🇧 EN / 🇹🇷 TR
Kategori Tümü / Systems Engineering & Business Analysis / Test Engineering / Software Engineering

Projects — GitHub Otomatik Senkronizasyonu

Repolar, GitHub Actions aracılığıyla her Pazartesi otomatik olarak çekilir.

Nasıl çalışır:

  1. fetch-github.js, GET /users/ferhattufekci/repos çağrısı yapar (REST API)
  2. Sabitlenmiş repolar GitHub GraphQL API ile çekilir
  3. Her repo için dil dağılımı GET /repos/{owner}/{repo}/languages ile alınır
  4. Yıldızlanan repolar GET /users/ferhattufekci/starred ile çekilir
  5. Kategori; repo adı, açıklaması ve topic'lerinden otomatik tespit edilir
  6. Sonuçlar data/github-repos.json, data/github-starred.json, data/github-meta.json dosyalarına kaydedilir

Projects sayfası bölümleri:

Bölüm Açıklama
📌 PINNED GitHub profilinde sabitlenmiş repolar
📂 ALL REPOSITORIES Tüm public repolar, yıldız sayısına göre sıralı
⭐ STARRED Ferhat'ın yıldızladığı repolar — değerli bulduğu kaynaklar (ilk 20 gösterilir, genişletilebilir)

Kategori filtresi PINNED ve ALL REPOSITORIES bölümlerine uygulanır.
Bölüm başlığı, seçilen filtre adını dinamik olarak gösterir.

Bir repoyu siteden gizlemek için:
scripts/fetch-github.js dosyasındaki EXCLUDE kümesine repo adını ekle.

Yeni repo oluşturulduğunda veya güncellendiğinde hiçbir manuel adım gerekmez.

SEO / AI Keşfedilebilirliği (GEO & AEO)

Blog ve Projects bölümleri client-side fetch() ile dolduruluyor; Googlebot bunu render eder ama GPTBot, PerplexityBot gibi birçok AI cevap motoru crawler'ı render etmez — sadece ham HTML'i okur. Bu içeriği o crawler'lara da görünür kılmak için özel olarak eklenenler:

Ne Nerede Amacı
<noscript> yedek içerik index.html, Projects ve Blog alt sayfalarının içinde JavaScript çalıştırmayan crawler'lar için ham HTML'de gerçek başlık/link/açıklama. JS'li normal tarayıcılarda görünmez — görsel veya duplicate-content etkisi yok.
llms.txt site köküne Bu sitenin ne olduğunu, ana sayfalarını ve güncel makale/proje listesini özetleyen düz metin dosyası (gelişen llms.txt standardı) — LLM tabanlı cevap motorları tarafından doğrudan çekilmesi amaçlanıyor.
scripts/build-static-seo.js scripts/ Yukarıdaki ikisini data/github-repos.json ve data/medium-all.json'dan yeniden üretir, böylece bayatlayamazlar. Ayrıca sitemap.xml'in <lastmod>'unu günceller — ama yalnızca gerçekten bir şey değiştiyse.
Person.knowsAbout index.html <head>'indeki JSON-LD Sitede zaten var olan <meta name="keywords"> listesinden türetilmiş, arama/AI için konu sinyalleri.
AI crawler izin listesi robots.txt GPTBot, ClaudeBot, PerplexityBot, Google-Extended ve diğerlerini açıkça listeler. Davranış değişmedi (joker Allow: / zaten kapsıyordu) — bu sadece niyeti belgeliyor.

build-static-seo.js, hem fetch-github.yml hem fetch-medium.yml içinde veri çekme adımından hemen sonra otomatik çalışır; böylece yedek içerik ve llms.txt, her zamanlanmış senkronizasyonda gerçek veriyle senkron kalır. Idempotent'tir — veri değişmediyse yeniden çalıştırmak hiçbir fark üretmez, dolayısıyla asla boş commit oluşturmaz.

Elle yeniden üretmek için:

node scripts/build-static-seo.js

Yerel Çalıştırma

# VS Code Live Server (önerilen)
# index.html üzerine sağ tıkla → Open with Live Server

# Veya Python ile
python3 -m http.server 8000

Lisans

Bu proje portföy ve tanıtım amaçlı yayımlanmıştır.
Tüm kişisel içerik, makaleler, görseller ve marka öğeleri Ferhat Tüfekçi'ye aittir.
Ticari kullanım, yeniden dağıtım veya türev çalışmalar için önceden yazılı izin alınması gerekmektedir.

Yazar

Yazar LinkedIn Medium

About

Personal portfolio. Medium articles & GitHub repos auto-synced via GitHub Actions. Blog with EN/TR filter. Projects with category filter & starred repos.

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages