From 486e34baf36812111c62d7dc35de0230bece042b Mon Sep 17 00:00:00 2001 From: suphicakir Date: Fri, 16 Oct 2026 08:43:47 +0300 Subject: [PATCH] fix: track src/data JSON files (gitignore matched every data/ dir) The view-counter ignore rule 'data/' also matched src/data/, so the site's JSON content was never committed and clean builds (Dokploy) failed. Anchor it to the repository root: '/data/'. Co-Authored-By: Claude Opus 5.5 --- .gitignore | 2 +- PROJECT_MEMORY.md | 2 + src/data/about.json | 47 ++++++++++++++++++++ src/data/blog.json | 77 ++++++++++++++++++++++++++++++++ src/data/categories.json | 9 ++++ src/data/contact.json | 38 ++++++++++++++++ src/data/home.json | 94 ++++++++++++++++++++++++++++++++++++++++ src/data/pages.json | 18 ++++++++ src/data/site.json | 45 +++++++++++++++++++ src/data/social.json | 7 +++ 10 files changed, 338 insertions(+), 1 deletion(-) create mode 100644 src/data/about.json create mode 100644 src/data/blog.json create mode 100644 src/data/categories.json create mode 100644 src/data/contact.json create mode 100644 src/data/home.json create mode 100644 src/data/pages.json create mode 100644 src/data/site.json create mode 100644 src/data/social.json diff --git a/.gitignore b/.gitignore index b7ce87b..b792851 100644 --- a/.gitignore +++ b/.gitignore @@ -24,4 +24,4 @@ pnpm-debug.log* .idea/ # local data (view counter SQLite) -data/ +/data/ diff --git a/PROJECT_MEMORY.md b/PROJECT_MEMORY.md index d4bb4bf..46c744e 100644 --- a/PROJECT_MEMORY.md +++ b/PROJECT_MEMORY.md @@ -71,6 +71,7 @@ | 2026-10-15 | Kanonik alan: apex `ta1sph.info`, www → 301 | SEO tekilleştirme | | 2026-10-15 | Fontlar self-host (Fontsource: Rubik + Inter) | Performans + gizlilik | | 2026-10-16 | Ek token'lar: `accent-fill`/`on-accent-fill`, `accent-text` (khaki'de fg'ye döner) | Ölçüm: ink/red 4.46, red-strong/khaki 3.85 → küçük metin AA'yı geçmiyordu. Kırmızı zeminli butonlar ≥19px bold | +| 2026-10-16 | Docker testleri **temiz git klonundan** yapılır (çalışma dizininden değil) | Yoksayılan/commit'lenmemiş dosyalar yerel testte görünmez; Dokploy repo'dan klonlar | | 2026-10-16 | Sıkıştırma konteyner içinde (`server.mjs` + `compression`), Traefik ayarı yok | Kullanıcının Dokploy'da ek middleware kurmasına gerek kalmaz | | 2026-10-16 | Docker taban imajı `node:24-slim` (LTS) | `node:sqlite` 24 ve 26'da uyarısız test edildi; 24 LTS Nisan 2028'e kadar destekli | | 2026-10-16 | Kalıcı veri için Dokploy'da named volume (bind mount değil) | Named volume ilk mount'ta imajdaki `node` sahipliğini alır; bind mount root olur → yazma hatası | @@ -106,6 +107,7 @@ ## 6. Değişiklik Günlüğü (en yeni üstte) +- 2026-10-16 | Yayına Al (fix) | `.gitignore` `data/` → `/data/`: `src/data/*.json` hiç commit'lenmemişti, Dokploy build'i kırıldı; temiz klon + Docker ile doğrulandı | `.gitignore`, `src/data/` - 2026-10-16 | Siteyi Kur A8 | Dockerfile, .dockerignore, compose, server.mjs (sıkıştırma + güvenlik başlıkları), /api/health, build-only bağımlılıklar devDeps'e; Docker'da uçtan uca test | `Dockerfile`, `.dockerignore`, `docker-compose.yml`, `server.mjs`, `src/pages/api/health.ts`, `src/lib/views.ts`, `package.json`, `README.md` - 2026-10-16 | Siteyi Kur A7 | OG görselleri (yazı başına + varsayılan), favicon seti + manifest, robots.txt, font alt kümeleme + preload, CSS inline, site denetim script'i, Lighthouse | `src/lib/og.ts`, `src/pages/{og,og-default.png,robots.txt,site.webmanifest}*`, `scripts/{generate-icons,subset-fonts,check-site}.mjs`, `public/`, `src/styles/fonts.css`, `Seo.astro`, `BaseLayout.astro`, `astro.config.mjs` - 2026-10-16 | Siteyi Kur A6 | Hakkımda, İletişim (Leaflet harita, gizlenmiş e-posta), Gizlilik/Lisans/Sorumluluk Reddi, 404, LICENSE dosyaları; PageHeader + CodeCopy ortak bileşenleri; axe temiz | `src/pages/{hakkimda,iletisim,[legal],404}.astro`, `src/content/legal/`, `src/data/{about,contact,pages}.json`, `src/components/{PageHeader,CodeCopy,Card}.astro`, `LICENSE*`, `global.css` diff --git a/src/data/about.json b/src/data/about.json new file mode 100644 index 0000000..1785a3e --- /dev/null +++ b/src/data/about.json @@ -0,0 +1,47 @@ +{ + "seo": { + "title": "Hakkımda", + "description": "Suphi Çakır (TA1SPH): DMR ID, favori talkgroup, kullandığım el telsizleri, sabit/mobil cihazlar ve antenler." + }, + "eyebrow": "Hakkımda", + "title": "Suphi Çakır", + "lead": "Amatör telsizci · TA1SPH", + "identity": { + "title": "Künye", + "items": [ + { "label": "Ad Soyad", "value": "Suphi Çakır", "icon": "tabler:user" }, + { "label": "Çağrı İşareti", "value": "TA1SPH", "icon": "tabler:antenna" }, + { "label": "DMR ID", "value": "2866151", "icon": "tabler:id" }, + { "label": "Favori TG", "value": "28690", "icon": "tabler:users-group" } + ] + }, + "equipment": [ + { + "title": "El Telsizleri", + "icon": "tabler:device-mobile", + "items": [ + { "name": "Tekser UV 99" }, + { "name": "Baofeng K5 Plus" }, + { "name": "Quansheng K1 Mini Kong" }, + { "name": "AnyTone 878" }, + { "name": "Baofeng DM1701", "note": "Hotspot, OpenGD77" }, + { "name": "Hytera P50 PoC", "note": "Yalnızca DigiVoice DMR için" } + ] + }, + { + "title": "Sabit / Mobil Cihazlar", + "icon": "tabler:car", + "items": [{ "name": "AnyTone 578" }, { "name": "Retevis RT95" }] + }, + { + "title": "Antenler", + "icon": "tabler:antenna", + "items": [ + { "name": "Diamond X30" }, + { "name": "Flowerpot", "note": "UHF/VHF" }, + { "name": "Moxon", "note": "UHF" }, + { "name": "Ground Plane", "note": "UHF" } + ] + } + ] +} diff --git a/src/data/blog.json b/src/data/blog.json new file mode 100644 index 0000000..33d6e59 --- /dev/null +++ b/src/data/blog.json @@ -0,0 +1,77 @@ +{ + "seo": { + "title": "Blog", + "description": "Amatör telsizcilik yazıları: DMR, antenler, röleler, hotspot, cihaz incelemeleri ve kendin yap projeleri." + }, + "list": { + "eyebrow": "Blog", + "title": "Yazılar", + "categoryEyebrow": "Kategori", + "tagEyebrow": "Etiket", + "tagTitle": "#{tag}", + "categoryDescription": "{name} kategorisindeki yazılar.", + "tagDescription": "\"{tag}\" etiketli yazılar.", + "pageTitle": "{title} — Sayfa {n}", + "empty": "Henüz yazı yok." + }, + "card": { + "readMore": "Devamını oku", + "readingTime": "{n} dk okuma" + }, + "dates": { + "created": "Oluşturuldu", + "updated": "Güncellendi" + }, + "pager": { + "label": "Sayfalar", + "first": "İlk", + "prev": "Önceki", + "next": "Sonraki", + "last": "Son", + "page": "Sayfa {n}" + }, + "sidebar": { + "label": "Blog kenar çubuğu", + "search": "Ara", + "searchLabel": "Yazılarda ara", + "searchPlaceholder": "Yazılarda ara…", + "searchNoResults": "Sonuç bulunamadı.", + "searchResults": "{n} sonuç", + "searchUnavailable": "Arama yalnızca derlenmiş sitede çalışır.", + "categories": "Kategoriler", + "featured": "Öne Çıkan Yazılar", + "tags": "Etiket Bulutu" + }, + "post": { + "breadcrumbLabel": "Konum", + "toc": "İçindekiler", + "shareLabel": "Paylaş", + "copyLink": "Bağlantıyı Kopyala", + "copied": "Bağlantı kopyalandı", + "nativeShare": "Paylaş…", + "copyCode": "Kopyala", + "codeCopied": "Kopyalandı", + "category": "Kategori", + "tags": "Etiketler", + "adjacentLabel": "Diğer yazılar", + "prev": "Önceki yazı", + "next": "Sonraki yazı", + "license": "Bu yazı {license} lisansıyla paylaşılmıştır; kaynak göstererek kopyalayabilir, düzenleyebilir ve aynı lisansla paylaşabilirsiniz.", + "licenseName": "CC BY-SA 4.0", + "licenseHref": "/lisans/" + }, + "diy": { + "title": "Sorumluluk Reddi", + "body": "Bu yazıdaki uygulamalar eğitim ve hobi amaçlıdır. Uygulamadan doğabilecek her türlü zarar, cihaz arızası ve mevzuata aykırılık sorumluluğu uygulayan kişiye aittir.", + "link": { "label": "Sorumluluk reddi metninin tamamı", "href": "/sorumluluk-reddi/" } + }, + "share": [ + { "id": "x", "label": "X'te paylaş", "icon": "tabler:brand-x", "url": "https://x.com/intent/post?url={url}&text={title}" }, + { "id": "facebook", "label": "Facebook'ta paylaş", "icon": "tabler:brand-facebook", "url": "https://www.facebook.com/sharer/sharer.php?u={url}" }, + { "id": "linkedin", "label": "LinkedIn'de paylaş", "icon": "tabler:brand-linkedin", "url": "https://www.linkedin.com/sharing/share-offsite/?url={url}" }, + { "id": "whatsapp", "label": "WhatsApp ile gönder", "icon": "tabler:brand-whatsapp", "url": "https://wa.me/?text={title}%20{url}" }, + { "id": "telegram", "label": "Telegram ile gönder", "icon": "tabler:brand-telegram", "url": "https://t.me/share/url?url={url}&text={title}" }, + { "id": "bluesky", "label": "Bluesky'da paylaş", "icon": "tabler:brand-bluesky", "url": "https://bsky.app/intent/compose?text={title}%20{url}" }, + { "id": "email", "label": "E-posta ile gönder", "icon": "tabler:mail", "url": "mailto:?subject={title}&body={url}" } + ] +} diff --git a/src/data/categories.json b/src/data/categories.json new file mode 100644 index 0000000..186cef8 --- /dev/null +++ b/src/data/categories.json @@ -0,0 +1,9 @@ +[ + { "slug": "dmr", "name": "DMR & Dijital Modlar", "description": "DMR, talkgroup'lar, kod plugları ve dijital ses modları.", "icon": "tabler:radio" }, + { "slug": "antenler", "name": "Antenler & DIY", "description": "Anten yapımı, ölçüm ve kendin yap projeleri.", "icon": "tabler:antenna" }, + { "slug": "cihazlar", "name": "Cihaz İncelemeleri", "description": "El telsizleri, mobil cihazlar ve aksesuarlar.", "icon": "tabler:device-mobile" }, + { "slug": "roleler", "name": "Röleler & Şebekeler", "description": "Röle kullanımı, frekanslar ve ton ayarları.", "icon": "tabler:building-broadcast-tower" }, + { "slug": "hotspot", "name": "Hotspot & Yazılım", "description": "Hotspot kurulumu, firmware ve yazılımlar.", "icon": "tabler:router" }, + { "slug": "mevzuat", "name": "Lisans & Mevzuat", "description": "Amatör telsizcilik lisansı ve mevzuat notları.", "icon": "tabler:license" }, + { "slug": "genel", "name": "Genel", "description": "Diğer notlar ve duyurular.", "icon": "tabler:notes" } +] diff --git a/src/data/contact.json b/src/data/contact.json new file mode 100644 index 0000000..41df17f --- /dev/null +++ b/src/data/contact.json @@ -0,0 +1,38 @@ +{ + "seo": { + "title": "İletişim", + "description": "TA1SPH ile iletişim: QTH İstanbul / Gaziosmanpaşa, locator KN41KB99HW, DMR talkgroup'ları, röleler, e-posta ve QRZ profilleri." + }, + "eyebrow": "İletişim", + "title": "İletişim", + "icon": "tabler:building-broadcast-tower", + "lead": "Telsizde, e-postayla ya da QRZ profillerim üzerinden ulaşabilirsiniz.", + "infoTitle": "İstasyon Bilgileri", + "map": { + "title": "Konum", + "lat": 41.08307, + "lng": 28.91094, + "zoom": 13, + "popup": "TA1SPH · KN41KB99HW", + "ariaLabel": "TA1SPH istasyon konumunu gösteren harita: İstanbul / Gaziosmanpaşa, locator KN41KB99HW", + "note": "Harita, locator karesinin merkezini (41.08307 K, 28.91094 D) yaklaşık olarak gösterir.", + "loading": "Harita yükleniyor…" + }, + "items": [ + { "label": "QTH", "icon": "tabler:map-pin", "values": ["İstanbul / Gaziosmanpaşa"] }, + { "label": "Locator", "icon": "tabler:grid-dots", "values": ["KN41KB99HW"] }, + { "label": "DMR TG", "icon": "tabler:radio", "values": ["28690", "28600", "28634"] }, + { + "label": "Röleler", + "icon": "tabler:building-broadcast-tower", + "values": [ + "Tekstilkent 439.200 MHz (Tx CTCSS 88.5 Hz)", + "TAMAD Esenyurt 439.250 MHz (Tx/Rx CTCSS 123.0 Hz)" + ] + }, + { "label": "E-posta", "icon": "tabler:mail", "email": "suphi@radio.org.tr" }, + { "label": "QRZ.com", "icon": "tabler:world", "href": "https://www.qrz.com/db/TA1SPH", "values": ["qrz.com/db/TA1SPH"] }, + { "label": "QRZ73", "icon": "tabler:address-book", "href": "https://qrz73.org.tr/callsign.php?call=TA1SPH", "values": ["qrz73.org.tr · TA1SPH"] }, + { "label": "TA-CallBook", "icon": "tabler:book", "href": "http://www.tacallbook.org/", "values": ["tacallbook.org"] } + ] +} diff --git a/src/data/home.json b/src/data/home.json new file mode 100644 index 0000000..c6d6d9f --- /dev/null +++ b/src/data/home.json @@ -0,0 +1,94 @@ +{ + "seo": { + "description": "TA1SPH Suphi Çakır'ın amatör telsizcilik notları: DMR, röleler, antenler, cihazlar ve faydalı Türkçe kaynaklar." + }, + "hero": { + "numeral": "73", + "tags": [ + { "icon": "tabler:antenna", "label": "TA1SPH" }, + { "icon": "tabler:map-pin", "label": "KN41KB" }, + { "icon": "tabler:building-broadcast-tower", "label": "İstanbul" } + ], + "asideTitle": "İstanbul'dan QRV", + "asideBody": "Gaziosmanpaşa'dan amatör telsizcilik üzerine notlar, denemeler ve kaynaklar.", + "asideLink": { "label": "İletişime Geç", "href": "/iletisim/" }, + "eyebrow": "TA1SPH", + "title": "Amatör Telsizcilik Notları", + "lead": "DMR, röleler, antenler ve cihazlar üzerine denemelerimi, öğrendiklerimi ve işe yarayan kaynakları paylaşıyorum.", + "ctas": [ + { "label": "Blog'u Oku", "href": "/blog/", "variant": "primary", "icon": "tabler:arrow-right" }, + { "label": "Hakkımda", "href": "/hakkimda/", "variant": "secondary" } + ] + }, + "sections": [ + { + "id": "ard", + "type": "feature", + "eyebrow": "Dernek", + "title": "Amatör Radyocular Derneği", + "body": "Amatör telsizciliği yaygınlaştırmak, eğitim vermek ve teknik projeler geliştirmek amacıyla kurulmuş bir dernek.", + "callsign": "YM1KTC", + "callsignLabel": "Kulüp çağrı işareti", + "icon": "tabler:users-group", + "link": { "label": "Derneği Ziyaret Et", "href": "https://radio.org.tr" } + }, + { + "id": "dmr", + "type": "feature", + "eyebrow": "Dijital Ses", + "title": "DMR Türkiye", + "body": "Türkiye'de DMR (Digital Mobile Radio) ile ilgilenen amatör telsizciler ve dijital haberleşme topluluğu için bir kaynak.", + "icon": "tabler:radio", + "link": { "label": "DMR Türkiye'ye Git", "href": "https://www.dmrturkiye.com" } + }, + { + "id": "qrv73", + "type": "feature", + "eyebrow": "Platform", + "title": "QRV73! Platformu", + "body": "Çevrimiçi radyo amatörleri platformu: amatör telsizciler için bilgi kaynakları, dokümanlar ve radyo amatörlerine ücretsiz sunulan yerli yazılımlar.", + "icon": "tabler:apps", + "link": { "label": "QRV73!'e Git", "href": "https://qrv73.com/" } + }, + { + "id": "qrz73", + "type": "feature", + "eyebrow": "Callbook", + "title": "QRZ73! Platformu", + "body": "Türkiye amatör telsizci veritabanı: çağrı işareti sorgulama, ekipman ve QSL tercihlerini paylaşabileceğiniz profiller, bant ve mod bilgisi.", + "icon": "tabler:address-book", + "link": { "label": "QRZ73!'e Git", "href": "https://qrz73.org.tr/" } + }, + { + "id": "telegram", + "type": "cards", + "eyebrow": "Topluluk", + "title": "Telegram Grupları", + "items": [ + { "title": "Amatör Telsizci", "href": "https://t.me/amatortelsizci", "icon": "tabler:brand-telegram" }, + { "title": "Çevrim Zamanı", "href": "https://t.me/cevrim_zamani", "icon": "tabler:brand-telegram" }, + { "title": "Amatör Radyocular Derneği (YM1KTC)", "href": "https://t.me/ym1ktc", "icon": "tabler:brand-telegram" } + ] + }, + { + "id": "latest", + "type": "latestPosts", + "eyebrow": "Blog", + "title": "Son Yazılar", + "count": 3, + "allLink": { "label": "Tüm Yazılar", "href": "/blog/" }, + "empty": "İlk yazılar çok yakında burada olacak." + }, + { + "id": "sites", + "type": "cards", + "eyebrow": "Kaynaklar", + "title": "Site Tanıtımları", + "items": [ + { "title": "Türkiye Röleleri", "description": "Türkiye'deki VHF ve UHF, analog ve dijital amatör telsiz röle frekansları, bölge bölge.", "href": "https://ta-role.com", "icon": "tabler:building-broadcast-tower" }, + { "title": "Türkiye Amatör Telsiz Röle Listesi", "description": "Türkiye'deki amatör telsiz rölelerinin konum, frekans, CTCSS tonu ve bant bilgileri.", "href": "https://amatortelsizcilik.com.tr/roleler", "icon": "tabler:list-details" }, + { "title": "Türkçe Logbook", "description": "QRZ73! üzerinde QSO kayıtlarınızı yönetebileceğiniz Türkçe logbook.", "href": "https://qrz73.org.tr/", "icon": "tabler:notebook" } + ] + } + ] +} diff --git a/src/data/pages.json b/src/data/pages.json new file mode 100644 index 0000000..8d8beab --- /dev/null +++ b/src/data/pages.json @@ -0,0 +1,18 @@ +{ + "legal": { + "eyebrow": "Yasal", + "updated": "Son güncelleme", + "notice": "Bu metin bilgilendirme amaçlıdır ve hukuki danışmanlık yerine geçmez." + }, + "notFound": { + "seoTitle": "Sayfa bulunamadı", + "description": "Aradığınız sayfa bulunamadı.", + "eyebrow": "Sayfa bulunamadı", + "title": "QRT — Bu sayfa yayında değil", + "lead": "Aradığınız sayfa taşınmış, silinmiş ya da hiç var olmamış olabilir. Frekansı değiştirip tekrar deneyin.", + "links": [ + { "label": "Ana Sayfa", "href": "/", "variant": "primary", "icon": "tabler:home" }, + { "label": "Blog", "href": "/blog/", "variant": "secondary", "icon": "tabler:article" } + ] + } +} diff --git a/src/data/site.json b/src/data/site.json new file mode 100644 index 0000000..3772885 --- /dev/null +++ b/src/data/site.json @@ -0,0 +1,45 @@ +{ + "name": "TA1SPH", + "title": "TA1SPH · Suphi Çakır", + "description": "TA1SPH Suphi Çakır'ın amatör telsizcilik notları: DMR, antenler, röleler, cihaz incelemeleri ve kendin yap (DIY) projeleri.", + "url": "https://ta1sph.info", + "lang": "tr", + "locale": "tr_TR", + "titleSeparator": " · ", + "author": { + "name": "Suphi Çakır", + "callsign": "TA1SPH", + "locator": "KN41KB" + }, + "postsPerPage": 6, + "nav": [ + { "label": "Ana Sayfa", "href": "/" }, + { "label": "Blog", "href": "/blog/" }, + { "label": "Hakkımda", "href": "/hakkimda/" }, + { "label": "İletişim", "href": "/iletisim/" } + ], + "footer": { + "about": "İstanbul'dan amatör telsizcilik üzerine notlar, denemeler ve faydalı kaynaklar.", + "quickLinksTitle": "Bağlantılar", + "legalTitle": "Yasal", + "socialTitle": "Sosyal Medya", + "rss": { "label": "RSS Akışı", "href": "/rss.xml" }, + "legal": [ + { "label": "Gizlilik Politikası", "href": "/gizlilik/" }, + { "label": "Lisans", "href": "/lisans/" }, + { "label": "Sorumluluk Reddi", "href": "/sorumluluk-reddi/" } + ], + "license": "İçerik CC BY-SA 4.0 · Kod MIT", + "signoff": "73 de TA1SPH" + }, + "ui": { + "skipToContent": "İçeriğe geç", + "mainNav": "Ana menü", + "footerNav": "Alt menü", + "menuOpen": "Menüyü aç", + "menuClose": "Menüyü kapat", + "themeToggle": "Temayı değiştir", + "newTab": "(yeni sekmede açılır)", + "home": "Ana sayfa" + } +} diff --git a/src/data/social.json b/src/data/social.json new file mode 100644 index 0000000..e31e169 --- /dev/null +++ b/src/data/social.json @@ -0,0 +1,7 @@ +[ + { "id": "instagram", "label": "Instagram", "href": "https://www.instagram.com/suphi.cakir/", "icon": "tabler:brand-instagram" }, + { "id": "facebook", "label": "Facebook", "href": "https://www.facebook.com/suphi.cakir", "icon": "tabler:brand-facebook" }, + { "id": "x", "label": "X (Twitter)", "href": "https://x.com/suphicakir", "icon": "tabler:brand-x", "handle": "@suphicakir" }, + { "id": "bluesky", "label": "Bluesky", "href": "https://bsky.app/profile/ta1sph.bsky.social", "icon": "tabler:brand-bluesky" }, + { "id": "youtube", "label": "YouTube", "href": "https://www.youtube.com/@suphcakirr", "icon": "tabler:brand-youtube" } +]